簡體   English   中英

Julia - 結構內部的C struct存儲為Julia中的指針

[英]Julia - C struct inside struct stored as pointer in Julia

我正在使用一個C庫,其中一個結構包含另一個結構(不是指針):

typedef struct {
    int a;
    double b;
} A;

typedef struct {
    A a;
    A b;
    int c;
} B;

示例初始化:

B* mkB() {
    A a = {2, 3.0};
    A b = {4, 5.0};
    B* rv = (B*)malloc(sizeof(B));
    rv->a = a;
    rv->b = b;
    rv->c = 6;
    return rv;
}

以下是Julia中的相應類型:

type A
    a::Cint
    b::Cdouble
end

type B
    a::A
    b::A
    c::Cint
end

現在sizeof(A) = 16 ,這是有道理的: Cint為4個字節,填充為4個字節,因此Cdouble對齊,而對於Cdouble 8個字節。

但Julia說sizeof(B) = 24 ,而fieldoffset只為字段ab設置了8個字節,只有當它們存儲為引用而不是值時才有意義:

julia> ofA = [Int(fieldoffset(A, i)) for i in 1:nfields(A)]'
1x2 Array{Int64,2}:
 0  8    

julia> ofB = [Int(fieldoffset(B, i)) for i in 1:nfields(B)]'
1x2 Array{Int64,2}:
 0  8  16

這是一個問題,因為如果不進行一些更改,就無法加載從C函數返回的這種結構的指針:

julia> x = A(2, 3.0); y = A(4, 5.0); z = B(x, y, 6);
julia> pz = pointer_from_objref(z);            #from Julia
julia> pb = ccall(("mkB", mylib), Ptr{B}, ()); #from C

julia> unsafe_load(reinterpret(Ptr{B}, pz))    #works as expected
B(A(2,3.0),A(4,5.0),6)

julia> unsafe_load(reinterpret(Ptr{B}, pb))    #segfaults

但是,給定C偏移量,可以單獨提取每個元素。 這里很明顯Julia將類型B中的類型A存儲為指針,而整個A存儲在C中內聯:

julia> unsafe_load(reinterpret(Ptr{A}, pb))        #from C
A(2,3.0)                                           #correct

julia> unsafe_load(reinterpret(Ptr{A}, pz))        #from Julia
A(1274099440,6.9455678017566e-310)                 #incorrect

julia> unsafe_load(unsafe_load(reinterpret(Ptr{Ptr{A}}, pz)))
A(2,3.0)                                           #correct

julia> unsafe_load(reinterpret(Ptr{Cint}, pb+32))  #from C
6                                                  #B.c offset 32 bytes

julia> unsafe_load(reinterpret(Ptr{Cint}, pz+16))  #from Julia
6                                                  #B.c offset 16 bytes

由於如果B是在C中創建的, Ptr{B}上的unsafe_load不起作用,我一直使用顯式偏移來構造兼容的Julia類型:

function B(p::Ptr{B})           #inner constructor for B
    of = [0, 16, 32]            #offsets in C
    jB = new()
    for i in 1:nfields(B)
        v = unsafe_load(reinterpret(Ptr{fieldtype(B,i)}, p + of[i]))
        setfield!(jB, fieldname(B, i), v)
    end
end

這可以從指向C分配內存的指針構建Julia類型,但是我需要更改一些字段值(在Julia中)並將指針傳遞回C函數。 pointer_from_objref對此不起作用,因為C期望struct元素作為值,但Julia將它們存儲為指針。 結構后面的每個成員都有錯誤的偏移量。

問題:如何獲得指向具有與C相同內存布局的數據的指針? 有沒有辦法告訴朱莉婭按價值存儲BaBb

而不是type ,將這些聲明為C兼容的內聯布局immutable immutable B ...給出sizeof(B) == 40

根據手冊

遞歸使用時,isbits類型以內聯方式存儲。 所有其他類型都存儲為指向數據的指針。 當鏡像在C中的另一個結構體內使用的值的結構時,必須不要嘗試手動復制字段,因為這不會保留正確的字段對齊。 相反,聲明一個不可變的isbits類型並使用它。 在Julia的翻譯中無法使用未命名的結構。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM