【问题标题】:Julia - C interface with nonfundamental typesJulia - 具有非基本类型的 C 接口
【发布时间】: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 的大小,不一定与机器的字大小相同。跨度>

标签: c julia


【解决方案1】:

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

【讨论】:

  • 好的,我把Int64到处都换成了Cint,把Array{contained,1}改成了Ptr{contained}。现在我想验证mk_mystruct 做了正确的事情,所以我定义了Base.show(m::mystruct)。我如何使用Ptr{contained} 而不是Array{contained,1} 来做到这一点? Julia中的指针和数组有什么关系吗?
  • @MatthewBedford 查看unsafe_wrap
猜你喜欢
  • 2016-08-02
  • 2023-03-08
  • 2017-12-29
  • 2021-01-25
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多