2016-11-07 20 views
3

私の質問は簡単ですが、それを行うための最良の方法は分かりません(またはJuliaは現時点でこのような方法を提供していません):どのようにフィールドを設定できますかJuliaのC構造体の値ですか?JuliaからC構造体のフィールド値を更新する

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

とジュリアにそれをコピーします:

あなたがCライブラリのツリーのノードを表すために、構造体の種類を持っている想像し

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

は今、あなたはへのポインタを持っていることを前提としnode_tはC言語で割り当てられ、Juliaのparentフィールドを更新したいと考えています。私はunsafe_store!がポインタで指し示された値を更新することがわかっていますが、parentフィールドのポインタオフセットを計算するのは面倒です(この場合、64ビットマシンではsizeof(Int) + sizeof(Ptr{node_t}) * 2になります)。同じことをする簡単な方法はありますか?

答えて

5

fieldoffset関数は、このユースケースのために提供されています。また、

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 

しかし、1つのフィールドを変更して、単に、全体immutableを保存する心配もありません。それは最適化されます。

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

julia> unsafe_load(k) 
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 
} 
+0

完璧な回答!私は 'fieldoffset'を知らなかったし、そのような最適化はうまくいく。大いに感謝する!。 – bicycle1885

関連する問題