在语言层面,究竟是什么`ccall`?

lcm*_*lin 11 syntax macros function ffi julia

我是朱莉娅的新手,我试图在语言层面理解它ccall是什么.在语法级别,它看起来像一个普通函数,但它在参数的显示方式上显然不同:

请注意,参数类型元组必须是文字元组,而不是元组值变量或表达式.

另外,如果我评估一个绑定到Julia REPL中的函数的变量,我会得到类似的东西

julia> max
max (generic function with 15 methods)
Run Code Online (Sandbox Code Playgroud)

但如果我尝试做同样的事情ccall:

julia> ccall
ERROR: syntax: invalid "ccall" syntax
Run Code Online (Sandbox Code Playgroud)

显然,这ccall是一种特殊的语法,但它也不是一个宏(没有@前缀,无效的宏使用会产生更具体的错误).那么,它是什么?它是用语言编写的东西,还是我可以用一些我不熟悉的语言构造来定义自己的东西?

如果它是一些烘焙的语法,为什么决定使用函数调用符号,而不是将其实现为宏或设计更可读和不同的语法?

Isa*_*ton 10

在当前的夜间(以及即将发布的0.6版本)中,您观察到的大部分特殊行为已被删除(请参阅此拉动请求).ccall不再是保留字,因此它可以用作函数或宏名称.

然而,仍然有一点点奇怪:定义一个被调用的3或4参数函数ccall是允许的,但实际上调用这样的函数会给出一个错误ccall argument types(其他数量的参数都可以).原因直接针对您的问题:

那么,它是什么?是它融入语言的东西吗?

是的,ccall虽然它不再是0.6中的关键字,但仍然以几种方式"融入"该语言:

  • :ccall([four args...])表达形式被识别和特殊处理期间的语法降低.这个降低步骤做了几件事,包括在调用中包装参数unsafe_convert,允许从Julia对象到C兼容对象的自定义转换; 以及拉出可能需要根植的参数以防止在引用期间对引用对象进行垃圾收集ccall.(请参阅code_lowered输出,或尝试该expand函数; 此处有关编译器的更多信息).
  • ccall需要在代码生成后端进行大量处理,包括:在指定的共享库中查找请求的函数名称,以及生成LLVM call指令 - 最终由LLVM Just-In-转换为特定于平台的机器代码时间编译器.(用code_llvm和看到不同的阶段code_native).

如果它是一些烘焙的语法,为什么决定使用函数调用符号,而不是将其实现为宏或设计更可读和不同的语法?

由于上面详述的原因,ccall无论它看起来像宏还是函数,都需要特殊处理.在这个邮件列表主题中,Julia创作者之一(Stefan Karpinski)评论了为什么不把它变成一个宏:

我想我们可以重新实现它作为一个宏,但那真的只是将魔力进一步推向下方.

至于"更可读和更独特的语法",也许这是一个品味问题.我不清楚为什么其他一些语法会更好(除了方便LuaJIT/CFFI样式的内联C语法解析,我是其中的粉丝).我唯一强烈的个人愿望是ccall将参数和类型输入相邻(例如ccall((:foo, :libbar), Void, (x::Int, y::Float))),因为使用较长的参数列表可能不方便.在0.6中,可以将此表单实现为宏!