我是朱莉娅(Julia)的新手,我正尝试在语言级别上了解 ccall
是什么。在语法级别上,它看起来像一个普通函数,但是显然它在接受参数时的行为方式不同:
此外,如果我评估绑定(bind)到Julia REPL中的函数的变量,则会得到类似
julia> max
max (generic function with 15 methods)
但是,如果我尝试对
ccall
做同样的事情:julia> ccall
ERROR: syntax: invalid "ccall" syntax
显然,
ccall
是一种特殊的语法,但它也不是宏(没有@
前缀,并且无效的宏用法会给出更具体的错误)。那是什么是语言中包含的东西,还是我可以用我不熟悉的某种语言构造来定义自己?而且,如果这是语法的一部分,为什么决定使用函数调用符号,而不是将其实现为宏或设计更具可读性和独特性的语法?
最佳答案
在当前的每晚(以及即将发布的0.6版本)中,您会观察到has been removed的许多特殊行为(请参阅this pull-request)。 ccall
不再是保留字,因此可以用作函数或宏名称。
但是仍然有一点奇怪:允许定义一个称为ccall
的3或4参数函数,但是实际上调用该函数将产生有关ccall argument types
的错误(其他数量的参数都可以)。原因直接与您的问题有关:
是的,尽管ccall
不再是0.6中的关键字,但仍通过以下几种方式“融入”该语言:
:ccall([four args...])
表达式形式,并识别specially handled。这个降低步骤做了几件事,包括将参数包装在对unsafe_convert
的调用中,该调用允许从Julia对象到C兼容对象的自定义转换;以及提取可能需要使用rooted的参数来防止在ccall
期间对引用对象进行垃圾回收。 (请参阅code_lowered
输出,或尝试使用expand
函数;有关编译器here的更多信息)。 ccall
在代码生成后端中需要extensive handling,包括:在指定的共享库中查找请求的函数名称,以及生成LLVM call
指令-最终由LLVM Just-翻译成平台特定的机器代码实时编译器。 (请参见code_llvm
和code_native
的不同阶段)。 由于上述原因,
ccall
看起来像是宏还是函数,需要进行特殊处理。在this mailing list thread中,Julia的一位创建者(Stefan Karpinski)评论了为什么不将其设为宏:至于“一种更具可读性和独特性的语法”,也许这是一个品味问题。我不清楚为什么还要使用其他一些语法(除了LuaJIT/CFFI风格的内联C语法解析的便利性之外,我是其中的忠实拥护者)。我对
ccall
的唯一强烈愿望就是将参数和类型输入到相邻的位置(例如ccall((:foo, :libbar), Void, (x::Int, y::Float))
),因为使用较长的参数列表可能会带来不便。在0.6中,可以将此形式实现为宏!