我有一个与C结构相对应的类型定义,如下所示:
{{1}}
如何在ccall中为c函数传递一个指向此类型的指针作为输入参数(即struct CStruct *)?
旧文档(v0.3)建议在ccall的输入参数列表中使用& var。但是,在v0.4文档中删除了该语句(同样,& var在v0.4中不起作用)。
答案 0 :(得分:0)
使用Ref{fakeCStruct}
:
r = Ref(fakeCStruct(3, 4))
ccall((:somefunction, "lib"), Void, (Ref{fakeCStruct},), r)
来自System Independent
表here中的Julia文档:
C name: | Julia base type
T* (where T represents an appropriately defined type) | Ref{T}
答案 1 :(得分:0)
为Julia对象分配内存,然后通过指针传递它:
type fakeCStruct
a::UInt8;
b::UInt32;
end
var = fakeCStruct(3,4)
var_p = Ptr{fakeCStruct}(pointer_from_objref(var))
ccall((:somefunc, "lib"), Void, (Ptr{fakeCStruct},), var_p)
(使用Ref {}并不适合我...使用Julia 0.4.0)
答案 2 :(得分:0)
尽管我绝对不是专家,但我还是迭代了一些对我有用的代码。希望这会帮助人们。在示例中,foo.c
被编译为共享库(在我的情况下为.dll
),并从foo.jl
进行调用。
foo.c
struct mystruct {
int a;
int b;
};
typedef struct mystruct mystruct_t;
int recvstruct(mystruct_t* st) {
printf("C %u, %u\n", st->a, st->b);
return 0;
}
mystruct_t* updatestruct(mystruct_t* st) {
// here we need to return the pointer, since Julia seems to
// pass a pointer to a copy of the struct
st->a = 10;
st->b = 11;
return st;
}
foo.jl
struct mystruct
a::Int32
b::Int32
end
function let_c_print_struct()
# Note that the function call automatically converts `mystruct(3, 4)` to `::Ref(..)`.
ccall((:recvstruct, libfile), Int32, (Ref{mystruct},), mystruct(3, 4))
end
function let_c_update_struct()
st = mystruct(5, 6)
ret = ccall((:updatestruct, libfile), Ref{ mystruct }, (Ref{ mystruct }, ), st)
@show st # st = mystruct(5, 6)
@show ret[] # ret[] = mystruct(10, 11)
end
关于共享库中数据的生命周期:我发现存储在内存中的对象仍然可用(我想它们超出了垃圾收集器的范围)。四个观察结果证明数据仍然可用:
unsafe_string
返回的值使用ccall
(取消引用指针)。查看unsafe_string(ccall(
的搜索结果。