printf and other varargs functions aren’t called the way normal C functions are
That’s not generally true. They aren’t called like a normal ANSI-C function because they’re typically required to be a normal K&R-C function. (But then those are often required to be the same, so you can usually get away with ignoring the difference.) In practice, some APIs that provide a ... varargs function use a void** implementation underneath (and expose that to users too) because the vararg itself can actually be fairly difficult to work with in the general case since it has a opaque representation.
I’ve successfully used printf with ccall before, just not with argument expansion on the Julia side. The message makes it look like ccall is already doing something macro-y (i.e. it seems not to expand arg…)
It has always been supported and this is the syntax. It doesn’t support mixing types though (llvm obviously support that just fine but we just don’t have a syntax for it…) I believe this is documented last time I check…
Note that on x86 (64bit only iirc) vararg floating point is one of the few cases this is needed. The calling convention requires the number of fp vararg to be passed in rax so without the ... the result may be wrong.
I don’t know if it works, but my idea use Ptr{Cvoid}… as your type in the case of printf because it’s going to recast all the arguments anyway based on what’s in the format string.
Well it does something based on the string for sure but that by no mean spare you from following the calling convention. The caller and callee always has to agree on that.
Of course you can make the calling convention passing everything by pointer for vararg, it’s not done for the same reason it’s not for normal argument: there are more efficient way to pass them.
There’s no C-level handling for this either. If you look at Meta.@lower, you’ll see that ccall is actually implemented as a macro. But the lowered form (foreigncall) also doesn’t define support for varargs of different types.