Julia ccall 接口和符号的问题 [英] Issue with Julia ccall interface and symbols
问题描述
我正在尝试使用 Julia 的 ccall
函数与 C 库进行交互.所有类型和指针都是正确的,并且下面的函数调用成功地返回了正确的答案(为简洁起见,此处未显示变量定义和设置).
I'm attemping to use Julia's ccall
function to interface with a C library. All the types and pointers are correct, and the below function call successfully returns the correct answer (variable defintion and setup not shown here for brevity).
ccall((:vDSP_convD, libacc), Void,
(Ptr{T}, Int64, Ptr{T}, Int64, Ptr{T}, Int64, UInt64, UInt64),
x_padded, 1, pointer(K, Ksize), -1, result, 1, Rsize, Ksize)
但是,如果我希望将函数名生成为符号,然后将其用作 ccall
的参数,则会失败.
However, if I wish to generate the function name as a symbol, and then use it as an argument to ccall
, it fails.
fname = symbol(string("vDSP_conv", "D"))
ccall((fname , libacc), Void,
(Ptr{T}, Int64, Ptr{T}, Int64, Ptr{T}, Int64, UInt64, UInt64),
x_padded, 1, pointer(K, Ksize), -1, result, 1, Rsize, Ksize)
错误是:
ERROR: LoadError: TypeError: conv: in ccall: first argument not a
pointer or valid constant expression, expected Ptr{T},
got Tuple{Symbol,ASCIIString}
如果我打印这两个命名版本的类型,我会得到
If I print the type of each of these two naming versions, I get
julia> println(typeof(:vDSP_convD))
Symbol
julia> println(typeof(fname))
Symbol
有没有办法让它工作?我猜我必须将它包装在宏或 @eval
中才能完成这项工作,但我很好奇为什么上述功能不能如图所示工作?
Is there a way to get this to work? I'm guessing that I will have to wrap this in a macro or @eval
to get this work, but I am curious as to why the above functionality doesn't work as shown?
任何帮助将不胜感激!
编辑
我最终将其包装在 @eval
块中以使其工作;但是,我仍然对后端逻辑感到好奇,为什么上述语法不起作用(为什么它有时将符号解释为指针,而其他时候则不)
I ended up wrapping this in an @eval
block to get it to work; however, I'm still curious as to the backend logic as to why the above syntax doesn't work (why it interprets a symbol as a pointer sometimes, and then not other times)
推荐答案
ccall
并不是真正的函数——它是一种使用 C ABI 转换为 C 函数调用的语法形式.要发出对 C 函数的调用,您需要能够静态解析函数的地址——这就是这个要求的来源.请注意,在 C 和 Julia 中,您还可以使用变量函数指针调用函数.在 Julia 中,有几种方法可以获得这样的指针,通常使用 dlopen
和 dlsym
.ccall
不会做的是通过非常量名称解析函数:这在 C 中是不可能的(无需自己构建查找表);在 Julia 中,您可以通过使用 eval
来做到这一点,正如您所知道的那样——但是这样做会产生编译器开销.这就是 ccall
不会自动执行此操作的原因:例如,您不想冒在循环中意外引入编译器开销的风险.
ccall
is not really a function – it's a syntactic form that is translated to a C function call using the C ABI. To emit a call to a C function, you need to be able to statically resolve the address of the function – that's where this requirement comes from. Note that in both C and Julia you can also call a function using a variable function pointer. In Julia, there are a few ways to get such a pointer, typically by using dlopen
and dlsym
. What ccall
won't do is resolve a function by non-constant name: this is impossible in C (without a building yourself a lookup table); in Julia you can do this, as you've figured out, by using eval
– but there is compiler overhead to doing this. That is why ccall
won't do this automatically: you don't want to run the risk of accidentally introducing compiler overhead in a loop, for example.
这篇关于Julia ccall 接口和符号的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!