Mat*_*ord 8 c struct pointers julia
我正在使用一个 C 库,其中一个结构包含另一个(不是指针):
typedef struct {
int a;
double b;
} A;
typedef struct {
A a;
A b;
int c;
} B;
Run Code Online (Sandbox Code Playgroud)
示例初始化:
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;
}
Run Code Online (Sandbox Code Playgroud)
以下是 Julia 中的相应类型:
type A
a::Cint
b::Cdouble
end
type B
a::A
b::A
c::Cint
end
Run Code Online (Sandbox Code Playgroud)
现在sizeof(A) = 16
,这是有道理的:a Cint
4 个字节,填充 4 个字节以便Cdouble
对齐,8 个字节用于Cdouble
.
但朱莉娅说sizeof(B) = 24
,和fieldoffset
看跌期权只有8个字节的领域a
和b
,这才有意义,如果它们被存储作为参考,而不是值:
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
Run Code Online (Sandbox Code Playgroud)
这是一个问题,因为从 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
Run Code Online (Sandbox Code Playgroud)
但是,给定 C 偏移量,可以单独提取每个元素。这里很明显 Julia 将 type 存储A
在 type 中B
作为指针,而整个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
Run Code Online (Sandbox Code Playgroud)
由于如果 B 是在 C 中创建的,则unsafe_load
aPtr{B}
不起作用,因此我一直使用显式偏移量来构造兼容的 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
Run Code Online (Sandbox Code Playgroud)
这可以从指向 C 分配内存的指针构建 Julia 类型,但随后我需要更改一些字段值(在 Julia 中)并将指针传递回 C 函数。 pointer_from_objref
不会为此工作,因为 C 期望结构元素作为值,但 Julia 将它们存储为指针。结构体之后的每个成员都会有错误的偏移量。
问题:如何获得指向与 C 中内存布局相同的数据的指针?有没有办法告诉 Julia 存储B.a
和B.b
按值?
归档时间: |
|
查看次数: |
1043 次 |
最近记录: |