[英]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
只為字段a
和b
設置了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相同內存布局的數據的指針? 有沒有辦法告訴朱莉婭按價值存儲Ba
和Bb
?
而不是type
,將這些聲明為C兼容的內聯布局immutable
。 immutable B ...
給出sizeof(B) == 40
。
根據手冊 :
遞歸使用時,isbits類型以內聯方式存儲。 所有其他類型都存儲為指向數據的指針。 當鏡像在C中的另一個結構體內使用的值的結構時,必須不要嘗試手動復制字段,因為這不會保留正確的字段對齊。 相反,聲明一個不可變的isbits類型並使用它。 在Julia的翻譯中無法使用未命名的結構。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.