Julia – C界面与非基本类型
我正在扩展使用C库的Julia包。 我需要从Julia调用一些C函数。 它们看起来像这样:
struct contained { int x; int y; int z; }; struct mystruct { int n; contained* arr; }; mystruct* mk_mystruct(int n, contained* arr); void use_mystruct(mystruct* foo);
我还在Julia中声明了相应的类型:
type contained x::Int64 y::Int64 z::Int64 end type mystruct n::Int64 arr::Array{contained, 1} end
要使用contained*
作为参数的函数进行ccall
,一切都可以正常处理contained*
为Ptr{Int64}
:
con = fill(0, 5, 3); mys = ccall((:mk_mystruct, "mylib"), Ptr{mystruct}, (Int64, Ptr{Int64}), n, con)
我认为这是有效的,因为contained
的内存布局与Int64的数组相同。 这也是Julia包中其他地方的完成方式。 但我知道检查返回的mystruct
的值的唯一方法是使用unsafe_load
取消引用它,此时Julia从段错误中崩溃。 在Julia中取消引用指针的正确方法是什么?
C库还包括漂亮的打印function,因此我可以将指针视为不透明,而不是在Julia中取消引用指针,而是将其传递回此C函数:
void print_mystruct(mystruct* foo, FILE* outputfile)
在C代码中,使用outputfile=stdout
调用它。 我如何用ccall
设置它? 这显然不起作用:
ccall((:print_mystruct, "mylib"), Void, (Ptr{mystruct}, Ptr{Void}), mys, stdout)
我应该把什么代替Ptr{Void}
和stdout
? Julia如何在C接口中实现I / O?
在Julia中声明类型时,必须声明与C相同的类型:
type contained x::Cint y::Cint z::Cint end type mystruct n::Cint arr::Ptr{contained} end
Julia类型Array{contained, 1}
将对应于C中的jl_value_t*
,而Julia类型Int
将对应于C中的intptr_t
。
我不知道获取stdout
句柄的平台无关方法,因为大多数平台都需要扩展C头宏来找出真正的符号名称。 例如,在macOS上,它被重命名为__stdoutp
:
julia> unsafe_load(cglobal(:__stdoutp, Ptr{Void})) Ptr{Void} @0x00007fff751f7348 julia> ccall(:fprintf, Csize_t, (Ptr{Void}, Cstring, Cint...), ans, "hi\n") hi 0x0000000000000003
您可能有兴趣查看Clang.jl包 ,它可以通过解析头文件自动生成这些定义。