我是朱莉娅(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_llvmcode_native的不同阶段)。



  • 由于上述原因,ccall看起来像是宏还是函数,需要进行特殊处理。在this mailing list thread中,Julia的一位创建者(Stefan Karpinski)评论了为什么不将其设为宏:



    至于“一种更具可读性和独特性的语法”,也许这是一个品味问题。我不清楚为什么还要使用其他一些语法(除了LuaJIT/CFFI风格的内联C语法解析的便利性之外,我是其中的忠实拥护者)。我对ccall的唯一强烈愿望就是将参数和类型输入到相邻的位置(例如ccall((:foo, :libbar), Void, (x::Int, y::Float))),因为使用较长的参数列表可能会带来不便。在0.6中,可以将此形式实现为宏!

    10-08 05:59