我正在尝试熟悉从Julia调用C
函数。
我有一些像isalnum
这样的简单函数的麻烦。
运行
ccall( (:isalnum, "libc"), Bool, (ASCIIString,), "k")
返回始终为false。
我也试过使用函数" div"返回分数的商和提醒。为了存储这两个值,我创建了一个类型
type Foo
A::Int64
B::Int64
end
然后运行
t = ccall( (:div, "libc"), Foo, (Int64,Int64,), 7,3)
但结果是错误的。
答案 0 :(得分:1)
C函数 int isalnum(int c); 接受一个int并返回一个int。您可以将字符传递给 ccall ,它将自动转换为Int64,但函数 convert(:: Type {Int64},:: ASCIIString)不存在。
此外,C将任何非零视为真,将Julia从 Int 转换为 Bool 时也是如此,但当返回类型定义为 Bool时而不是 Int64 它不起作用。
julia> ccall((:isalnum,"libc"),Int64,(Int64,),'k')
8
您可以将非整数作为参数传递,因为会隐式调用convert,但定义正确的返回类型很重要。
julia> convert(Bool,ccall((:isalnum,"libc"),Int64,(Int64,),'k'))
true
并通过比较
julia> convert(Bool,ccall((:isalnum,"libc"),Int64,(Int64,),' '))
false
答案 1 :(得分:1)
不幸的是,Julia目前不支持从ccalls返回结构。实现这一点的open pull request在0.3发布周期中落到了裂缝中并且没有合并。如果支持它(它将很快在主分支上),您将使用不可变结构使其工作。像这样:
julia> immutable Cdiv_t
q::Cint
r::Cint
end
julia> ccall(:div, Cdiv_t, (Cint,Cint), 7, 3)
Cdiv_t(2,2)
正如您所看到的,这已被破坏,因为Cdiv_t
结构的其余部分不正确(它当前将始终与商部分相同)。有必要使用不可变结构,因为可变结构需要将其组件作为单独分配的值存储在堆上 - 这与C结构布局不兼容。由于Cdiv_t
是不可变的,因此它的组件可以内联存储,这就是C的作用。
另请注意使用Cint
作为C int
类型的Julia端镜像。这总是被定义,以便它是与C的int
类型相对应的正确类型 - 这并不总是那么容易确定。调用C和Fortran的章节包含与C类型对应的a full list Julia类型。您通常希望在Julia代码中使用中间列名称,因为它们可以在任何地方使用,而不仅仅是在您的系统上。