Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

At a language level, what exactly is `ccall`?

I'm new to Julia, and I'm trying to understand, at the language level, what ccall is. At the syntax level, it looks like a normal function, but it clearly doesn't behave the same way in how it takes its arguments:

Note that the argument type tuple must be a literal tuple, and not a tuple-valued variable or expression.

Additionally, if I evaluate a variable bound to a function in the Julia REPL, I get something like

julia> max
max (generic function with 15 methods)

But if I try to do the same with ccall:

julia> ccall
ERROR: syntax: invalid "ccall" syntax

Clearly, ccall is a special piece of syntax, but it's also not a macro (no @ prefix, and invalid macro usage gives a more specific error). So, what is it? Is it something baked into the language, or something I could define myself with some language construct I'm not familiar with?

And if it is some baked-in piece of syntax, why was it decided to use function call notation, instead of implementing it as a macro or designing a more readable and distinct syntax?

like image 824
lcmylin Avatar asked Feb 15 '17 23:02

lcmylin


People also ask

Is B2 considered fluent?

Level B2: Basic FluencyReaching B2 is generally considered by most people as having basic fluency. You'll have a working vocabulary of around 4000 words.


1 Answers

In the current nightly (and thus, upcoming 0.6 release), much of the special behavior you observe has been removed (see this pull-request). ccall is no longer a reserved word, so it can be used as a function or macro name.

However there is still a slight oddity: defining a 3- or 4-argument function called ccall is allowed, but actually calling such a function will give an error about ccall argument types (other numbers of arguments are ok). The reasons go directly to your question:

So, what is it? Is it something baked into the language

Yes, ccall, though it will no longer be a keyword in 0.6, is still "baked in" to the language in several ways:

  • the :ccall([four args...]) expression form is recognized and specially handled during syntax lowering. This lowering step does several things including wrapping arguments in a call to unsafe_convert, which allows for customized conversion from Julia objects to C-compatible objects; as well as pulling out arguments that might need to be rooted to prevent garbage collection of a referenced object during the ccall. (see code_lowered output, or try the expand function; more info on the compiler here).
  • ccall requires extensive handling in the code generation backend, including: look-up of the requested function name in the specified shared library, and generation of an LLVM call instruction -- which is eventually translated to platform-specific machine code by the LLVM Just-In-Time compiler. (see the different stages with code_llvm and code_native).

And if it is some baked-in piece of syntax, why was it decided to use function call notation, instead of implementing it as a macro or designing a more readable and distinct syntax?

For the reasons detailed above, ccall requires special handling whether it looks like a macro or a function. In this mailing list thread, one of the Julia creators (Stefan Karpinski) commented on why not to make it a macro:

I suppose we could reimplement it as a macro, but that would really just be pushing the magic further down.

As far as "a more readable and distinct syntax", perhaps that is a matter of taste. It's not clear to me why some other syntax would be preferable (except for the convenience of a LuaJIT/CFFI-style inline C syntax parsing, of which I am a fan). My only strong personal wish for ccall would be to have arguments and types entered adjacent (e.g. ccall((:foo, :libbar), Void, (x::Int, y::Float))), because working with longer argument lists can be inconvenient. In 0.6 it will be possible to implement this form as a macro!

like image 76
Isaiah Norton Avatar answered Oct 28 '22 05:10

Isaiah Norton