# What Julia type maps to a C type containing nested structs?

**URL:** https://discourse.julialang.org/t/what-julia-type-maps-to-a-c-type-containing-nested-structs/4116
**Category:** General Usage
**Tags:** question, ccall
**Created:** [June 6, 2017, 9:31pm UTC](https://discourse.julialang.org/t/what-julia-type-maps-to-a-c-type-containing-nested-structs/4116 "2017-06-06T21:31:42Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![DemiMarie](https://avatars.discourse-cdn.com/v4/letter/d/43a26b/32.png) [@DemiMarie](https://discourse.julialang.org/u/DemiMarie)
#### Post date: [June 6, 2017, 9:31pm UTC](https://discourse.julialang.org/t/what-julia-type-maps-to-a-c-type-containing-nested-structs/4116/1 "2017-06-06T21:31:42Z")

</div>

Suppose I have a C type like this:

```nohighlight
struct foo {
   int x;
   char y;
};
struct bar {
   struct foo q;
   int y;
};

```

and I need to be able to modify `bar.q.x` in-place, or it is modified by a C function that I pass the struct’s address to.

What is the proper Julia type declaration?

---

<div class="post-metadata">

### Author: ![ihnorton](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihnorton/32/26_2.png) [@ihnorton](https://discourse.julialang.org/u/ihnorton)
#### Post date: [June 6, 2017, 9:55pm UTC](https://discourse.julialang.org/t/what-julia-type-maps-to-a-c-type-containing-nested-structs/4116/2 "2017-06-06T21:55:28Z")

</div>

> [@DemiMarie](#):
>
> What is the proper Julia type declaration?

```julia
julia> struct Foo
           x::Int
           y::UInt8
       end

julia> struct Bar
           q::Foo
           y::Int
       end

julia> sizeof(Bar)
24

julia> map(x->fieldoffset(Bar,x), 1:nfields(Bar))
2-element Array{UInt64,1}:
 0x0000000000000000
 0x0000000000000010

```

> [@DemiMarie](#):
>
> need to be able to modify bar.q.x in-place

The object may be stored in a `Ref`: `mb = Ref(Bar(Foo(1,0x8), 42))`, the top-level content of which is mutable; unfortunately, updating the nested contents doesn’t have a convenient syntax yet:

> <https://github.com/JuliaLang/julia/pull/21912>
>
> I like immutables, I really do, they're simple to work with, fast, don't cause a…llocations. Really the only thing that bothers me about them is that they're well, immutable, making them a bit of pain to work with, esp. when wanting to construct one incrementally. So here's an attempt to remedy that.
> Example usage:
> 
> \`\`\`
> julia\> struct Foo
> a::Int
> end
> 
> julia\> x = Foo(1)
> Foo(1)
> 
> julia\> x@a = 2
> Foo(2)
> 
> julia\> x
> Foo(2)
> \`\`\`
> 
> The ways this works is that under the hood, it creates a new immutable object with the specified field modified and then assigns it back to the appropriate place. Syntax wise, everything to the left of the \`@\` is what's being assigned to, everything to the right of the \`@\` is what is to be modified. E.g.
> 
> \`\`\`
> struct Foo4; d::Int; end
> struct Foo3; c::Foo4; end
> mutable struct Foo2; b::Foo3; end
> struct Foo1; a::Foo2; end
> x = Foo1(Foo2(Foo3(Foo4(1))))
> x.a.b@c.d = 2
> julia\> x
> Foo1(Foo2(Foo3(Foo4(2))))
> \`\`\`
> 
> Internally, everything to the right of the \`@\` gets lowered to \`setindex\` (no bang) and \`setfield\` (also no bang), which are overridable by the user. The intent is to disallow \`setfield\` for immutables that have a non-default inner constructor, allowing the user to provide their own which checks any required invariants. That part isn't implemented here yet, however.
> 
> Lastly, LLVM isn't currently too happy about the IR this generates, so I'm working on making that happen to make sure this actually performs ok. I think from the julia side, this is pretty much the extent of it though. Pretty much untested at the moment. I want to get the LLVM side of things done first. With that in mind, feel free to check out this branch and see if you like it.
> 
> One motivating example here is of course efficient, generic fixed size arrays, so here's an example of that:
> \`\`\`
> mutable struct MArray{Size, T, D, L} \<: AbstractArray{T, D}
> data::NTuple{L, T}
> end
> 
> Base.size(::MArray{Size}) where {Size} = tuple(Size.parameters...)
> @inline to\_linear\_index(::Type{Tuple{}}, idxs, stride) = 1
> @inline to\_linear\_index(::Type, idxs::Tuple{}, stride) = 1
> @inline to\_linear\_index(::Type{Tuple{A}}, idxs, stride) where {A} = idxs\[1\]
> @inline to\_linear\_index(::Type{Tuple{A,B}}, idxs, stride) where {A, B} = A\*(idxs\[1\]-1) + idxs\[2\]
> @inline to\_linear\_index(T::Type{\<:Tuple{A, Vararg{Any}}}, idxs, stride) where A =
> (stride \* (idxs\[1\]-1)) + to\_linear\_index(Base.tuple\_type\_tail(T), idxs\[2:end\], stride \* A)
> function Base.setindex!(a::MArray{Size}, v, idxs...) where Size
> @inbounds a.data@\[to\_linear\_index(Size, idxs, 1)\] = v
> v
> end
> Base.getindex(a::MArray{Size}, idxs...) where {Size} = a.data\[to\_linear\_index(Size, idxs, 1)\]
> 
> a = MArray{Tuple{2, 2}, Int, 2, 4}((1,2,3,4))
> b = \[1 2; 3 4\]
> c = \[4 5; 6 7\]
> 
> 
> \# Look ma, no allocations
> julia\> @benchmark A\_mul\_B!(a, b, c)
> BenchmarkTools.Trial:
> memory estimate: 0 bytes
> allocs estimate: 0
> --------------
> minimum time: 86.193 ns (0.00% GC)
> median time: 86.993 ns (0.00% GC)
> mean time: 87.978 ns (0.00% GC)
> maximum time: 3.282 μs (0.00% GC)
> --------------
> samples: 10000
> evals/sample: 961
> \`\`\`
> 
> Fixes #11902
> Supersedes #12113

(I believe there is a macro or package around to make that easier in the meantime, but I can’t find it at the moment. Hopefully someone else will provide a link)

---

<div class="post-metadata">

### Author: ![yuyichao](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yuyichao/32/20_2.png) [@yuyichao](https://discourse.julialang.org/u/yuyichao)
#### Post date: [June 6, 2017, 9:56pm UTC](https://discourse.julialang.org/t/what-julia-type-maps-to-a-c-type-containing-nested-structs/4116/3 "2017-06-06T21:56:02Z")

</div>

The most generic way to do it is to make both immutable and use a `Ref{bar}()` as the mutable container. For now you can load fields without much problem. If you need to mutate field, you’ll need to do some pointer arithmetic manually now and [WIP: Make mutating immutables easier by Keno · Pull Request #21912 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/21912) will provide full support for it.
