bicycle1885 - 1 year ago 67
C Question

# Updating a field value of a C struct from Julia

My question is simple but I don't know the best way to do that (or Julia doesn't offer such a way at the moment): how can I set a field value of a C struct from Julia?

Imagine you have a struct type to represent a node of a tree in a C library:

``````typedef struct node_s
{
int type;
node_t* next;
node_t* children;
node_t* parent;
} node_t;
``````

and copy it in Julia:

``````immutable node_t
typ::Cint
next::Ptr{node_t}
children::Ptr{node_t}
parent::Ptr{node_t}
end
``````

Now assume that you have a pointer to
`node_t`
allocated in C and want to update the
`parent`
field in Julia. I know we have
`unsafe_store!`
to update a value pointed by a pointer, but it's cumbersome to calculate the pointer offset of the
`parent`
field (in this case, it would be
`sizeof(Int) + sizeof(Ptr{node_t}) * 2`
on my 64-bit machine). Is there any simpler way to do the same thing?

The `fieldoffset` function is provided for this use case:

``````julia> immutable node_t
typ::Cint
next::Ptr{node_t}
children::Ptr{node_t}
parent::Ptr{node_t}
end

julia> fieldoffset(node_t, 1)
0x0000000000000000

julia> fieldoffset(node_t, 2)
0x0000000000000008

julia> fieldoffset(node_t, 3)
0x0000000000000010

julia> fieldoffset(node_t, 4)
0x0000000000000018
``````

But also don't be worried about simply storing the whole `immutable`, with one field changed; it will be optimized away.

``````julia> k = Ptr{node_t}(Libc.malloc(sizeof(node_t)))
Ptr{node_t} @0x00000000036194c0

node_t(29544064,Ptr{node_t} @0x3038662d34363a34,Ptr{node_t} @0x3a386e2d3832313a,Ptr{node_t} @0x34363a32333a3631)

julia> update_parent(x::node_t, n::Ptr{node_t}) =
node_t(x.typ, x.next, x.children, n)
update_parent (generic function with 1 method)

julia> mutate!(k) = unsafe_store!(k, update_parent(unsafe_load(k), Ptr{node_t}(0)))
mutate! (generic function with 1 method)

julia> @code_llvm mutate!(k)

define %node_t* @"julia_mutate!_70963"(%node_t*) #0 {
top:
%1 = load %node_t, %node_t* %0, align 1
%.fca.3.insert = insertvalue %node_t %1, %node_t* null, 3
store %node_t %.fca.3.insert, %node_t* %0, align 1
ret %node_t* %0
}
``````
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download