# How to get reference to the field of mutable struct

**URL:** <https://discourse.julialang.org/t/how-to-get-reference-to-the-field-of-mutable-struct/125222>\
**Category:** General Usage\
**Tags:** question\
**Created:** [January 26, 2025, 11:36am UTC](https://discourse.julialang.org/t/how-to-get-reference-to-the-field-of-mutable-struct/125222 "2025-01-26T11:36:27Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pedro](https://avatars.discourse-cdn.com/v4/letter/p/919ad9/32.png) [@Pedro](https://discourse.julialang.org/u/Pedro)\
**Post date:** [January 26, 2025, 11:36am UTC](https://discourse.julialang.org/t/how-to-get-reference-to-the-field-of-mutable-struct/125222/1 "2025-01-26T11:36:28Z")

</div>

How one can create the reference to the field of the instantiated `mutable struct`?

Let’s say I have a mutable struct `A` defined as

```julia
mutable struct A
    v1::Int
    v2::Float64
end

```

and an instance of this structure `a = A(0, 0.0)`.

I would like to get reference `ref_a_v1` to the field `v1` of object `a`, so that

```julia
ref_a_v1[] = 4

```

will result in changing the value of `a.v1` to `4`.

At the beginning, I thought `Ref(a.v1)` would work, but this obviously won’t work, since it is equivalent to `Ref(0)`, assuming that `a.v1 = 0`.

At this point, the only idea how I can handle it is creating mutable struct with references as a fields, i.e.,

```julia
mutable struct A
    v1::Ref{Int}
    v2::Ref{Float64}
end

```

however, it does not seem like a appropriate solution.

---

<div class="post-metadata">

**Author:** ![g-gundam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/g-gundam/32/47593_2.png) [@g-gundam](https://discourse.julialang.org/u/g-gundam)\
**Post date:** [January 26, 2025, 1:08pm UTC](https://discourse.julialang.org/t/how-to-get-reference-to-the-field-of-mutable-struct/125222/2 "2025-01-26T13:08:19Z")

</div>

How do you feel about this?

```julia-repl
julia> a = A(0, 0.0)
A(0, 0.0)

julia> ref_a = Ref(a)
Base.RefValue{A}(A(0, 0.0))

julia> ref_a[].v1 = 5
5

julia> a
A(5, 0.0)

```

It’s not as direct as what you originally wanted, but it seems to do what you want.

---

<div class="post-metadata">

**Author:** ![Pedro](https://avatars.discourse-cdn.com/v4/letter/p/919ad9/32.png) [@Pedro](https://discourse.julialang.org/u/Pedro)\
**Post date:** [January 26, 2025, 1:32pm UTC](https://discourse.julialang.org/t/how-to-get-reference-to-the-field-of-mutable-struct/125222/3 "2025-01-26T13:32:05Z")

</div>

I am aware of the approach you proposed, but unfortunately, it does not solve my case, since I need pass some struct field’s references into `ccall`.

At this moment, I figure out that I could alternatively use `Ptr`.

```julia
mutable struct A
    v1::Int
    v2::Float64
end

a = A(1, 0.0)

p_a = Ptr{A}(pointer_from_objref(a))
p_v1 = Ptr{Int}(p_a)
p_v2 = Ptr{Float64}(p_a + sizeof(Ptr))

unsafe_store!(p_v1, 45)
unsafe_store!(p_v2, 100.0)
a

```

However, this approach is fragile, since it depends on the order of fields in `struct A`.

---

<div class="post-metadata">

**Author:** ![PatrickHaecker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/patrickhaecker/32/222891_2.png) [@PatrickHaecker](https://discourse.julialang.org/u/PatrickHaecker)\
**Post date:** [January 27, 2025, 6:13pm UTC](https://discourse.julialang.org/t/how-to-get-reference-to-the-field-of-mutable-struct/125222/4 "2025-01-27T18:13:31Z")

</div>

> However, this approach is fragile, since it depends on the order of fields in `struct A`.

You can use `fieldoffset` instead if `sizeof` to make the pointer calculation robust. And when you are at it, you should probably also use `fieldtype`.

Then your two lines would be changed to

```julia
p_v1 = Ptr{fieldtype(A, 1)}(p_a + fieldoffset(A, 1))
p_v2 = Ptr{fieldtype(A, 2)}(p_a + fieldoffset(A, 2))

```

---

<div class="post-metadata">

**Author:** ![PatrickHaecker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/patrickhaecker/32/222891_2.png) [@PatrickHaecker](https://discourse.julialang.org/u/PatrickHaecker)\
**Post date:** [January 27, 2025, 6:54pm UTC](https://discourse.julialang.org/t/how-to-get-reference-to-the-field-of-mutable-struct/125222/5 "2025-01-27T18:54:45Z")

</div>

> How one can create the reference to the field of the instantiated `mutable struct`?

I am just [learning about this stuff](https://docs.julialang.org/en/v1/devdocs/object/), but I think this is impossible. I think the reason is that an `isbits` value like an `Int` or a `Float64` can be “boxed” and therefore referenced, but an `isbits` value inside a struct cannot be “boxed”.

I think these are your options:

- Use a pointer instead of a reference
- Wrap your `isbits` value into a mutable struct by using e.g. `Ref`
- Use properties to hide this wrapping

As [shown in the documentation](https://docs.julialang.org/en/v1/manual/interfaces/#man-instance-properties) this could look like (I only implemented `getproperty`, you can define `setproperty!` yourself):

```julia
mutable struct A
    v1_ref::Ref{Int}
    v2_ref::Ref{Float64}
end

A(v1::Int, v2::Float64) = A(Ref{Int}(v1), Ref{Float64}(v2))

Base.propertynames(::A, private::Bool=false) = private ? (:v1, :v2, :v1_ref, :v2_ref) : (:v1, :v2)

function Base.getproperty(a::A, s::Symbol)
    s === :v1 && return getfield(a, :v1_ref)[]
    s === :v2 && return getfield(a, :v2_ref)[]
    return getfield(a, s)
end

```

Using it:

```julia
a = A(0, 0.0)

julia> a.v1
0

julia> ref_a_v1 = a.v1_ref
Base.RefValue{Int64}(0)

julia> ref_a_v1[] = 4
4

julia> a.v1
4

```

---

<div class="post-metadata">

**Author:** ![Mason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mason/32/2423_2.png) [@Mason](https://discourse.julialang.org/u/Mason)\
**Post date:** [January 27, 2025, 7:27pm UTC](https://discourse.julialang.org/t/how-to-get-reference-to-the-field-of-mutable-struct/125222/6 "2025-01-27T19:27:27Z")

</div>

I’ve defined custom `PropertyRef`s before like so:

```julia
struct PropertyRef{prop, T} <: Ref{T}
    data::T
end
PropertyRef(x::T, prop::Symbol) where {T} = PropertyRef{prop, T}(x)
Base.getindex(x::PropertyRef{prop}) where {prop} = getproperty(x.data, prop)
Base.setindex!(x::PropertyRef{prop}, y) where {prop} = setproperty!(x.data, prop, y)

```

Here it is in action

```julia-repl
julia> a = A(1, 2.0);

julia> x = PropertyRef(a, :v1)
PropertyRef{:v1, A}(A(1, 2.0))

julia> x[]
1

julia> x[] += 1
2

julia> a # mutated!
A(2, 2.0)

```
