【发布时间】:2017-02-05 08:41:18
【问题描述】:
我正在扩展一个使用 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 库还包括漂亮的打印函数,因此我可以将指针视为不透明指针并将其传递回此 C 函数,而不是取消对 Julia 中的指针的引用:
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?
【问题讨论】:
-
为什么要用
Int64作为C的int的对应类型?int通常是 32 位,可能窄到 16 位,也可以是许多其他更大的尺寸。 -
其实我用的是
Int,但是因为Int在我的机器上意味着Int64,所以我把Int64放在上面的代码中,这样就不会混淆了。我的理解是Julia检测到Int的合适大小,所以在这台机器上C的int也是64位。对吗? -
C 中
int的大小由编译器和选项控制,而不是处理器。由于各种原因,32 位和 64 位int都可以在 64 位机器的编译器中找到。 -
正确的 int 类型是
Cint,它将解析为 C 中int的大小,不一定与机器的字大小相同。跨度>