我正在扩展使用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);
Run Code Online (Sandbox Code Playgroud)
我还在Julia中声明了相应的类型:
type contained
x::Int64
y::Int64
z::Int64
end
type mystruct
n::Int64
arr::Array{contained, 1}
end
Run Code Online (Sandbox Code Playgroud)
要ccall内搭一件功能contained*作为参数,一切正常治疗contained*为Ptr{Int64}:
con = fill(0, 5, 3);
mys = ccall((:mk_mystruct, "mylib"), Ptr{mystruct}, (Int64, Ptr{Int64}), n, con)
Run Code Online (Sandbox Code Playgroud)
我认为这是有效的,因为它contained具有与Int64数组相同的内存布局.这也是Julia包中其他地方的完成方式.但我知道检查返回值的唯一方法mystruct是取消引用它unsafe_load,此时Julia从段错误中崩溃.在Julia中取消引用指针的正确方法是什么?
C库还包括漂亮的打印功能,因此我可以将指针视为不透明,而不是在Julia中取消引用指针,而是将其传递回此C函数:
void print_mystruct(mystruct* foo, FILE* outputfile)
Run Code Online (Sandbox Code Playgroud)
在C代码中,调用它outputfile=stdout.我该如何设置ccall?这显然不起作用:
ccall((:print_mystruct, "mylib"), Void, (Ptr{mystruct}, Ptr{Void}), mys, stdout)
Run Code Online (Sandbox Code Playgroud)
我该怎么做而不是Ptr{Void}和stdout?Julia如何在C接口中实现I/O?
小智 4
在 Julia 中声明类型时,必须声明与 C 相同的类型:
type contained
x::Cint
y::Cint
z::Cint
end
type mystruct
n::Cint
arr::Ptr{contained}
end
Run Code Online (Sandbox Code Playgroud)
Julia 类型Array{contained, 1}将对应于jl_value_t*C 语言,而 Julia 类型Int将对应于intptr_tC 语言。
我不知道有一种与平台无关的方法来获取 的句柄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
Run Code Online (Sandbox Code Playgroud)
您可能有兴趣查看Clang.jl 包,它可以通过解析头文件自动生成这些定义。
| 归档时间: |
|
| 查看次数: |
313 次 |
| 最近记录: |