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包 ,它可以通过解析头文件自动生成这些定义。