Splicing in arguments into a ccall #1315

Open
timholy opened this Issue Sep 27, 2012 · 4 comments

Projects

None yet

6 participants

@timholy
The Julia Language member

Conceptually related to #1313.

If I try defining a function this way:

@eval begin
    function mylseek(args...)
        cpos = ccall(:lseek, FileOffset, (Int32, FileOffset, Int32), args...)
    end
end

then I get:

julia> s = open("h5test.c")
IOStream(<file h5test.c>)

julia> mylseek(fd(s), 5, 0)
error compiling mylseek: ccall: wrong number of arguments to C function

One workaround is the following:

ccallargs = Any[:(:lseek), FileOffset, expr(:tuple, Any[Int32, FileOffset, Int32]), :(args[1]), :(args[2]), :(args[3])]
ex = expr(:ccall, ccallargs)
@eval begin
    function mylseek(args...)
        $ex
    end
end

julia> mylseek(fd(s), 11, 0)
11

Perhaps there is a less-awkward syntax? If not, should we add a ccallexpr function to the library that would build those expressions?

@JeffBezanson
The Julia Language member

I believe this can't be done portably except for functions taking a va_list, and even then it's tricky.
In your example the metaprogramming is unnecessary; you can use a varargs julia function with an "if" case for various lengths, and pass args[1], args[2], etc. to the ccall.

@timholy
The Julia Language member

I found a way to do what I wanted, although I'm sure I'm handling a much more specific case than you're envisioning. Would you please check https://github.com/timholy/julia_hdf5/blob/master/hdf5.jl and see whether the section marked ### Utilities for generating ccall wrapper functions programmatically ### has anything of general interest? If not, it can continue to live in the HDF5 wrapper.

@vtjnash
The Julia Language member

previously mentioned code now now lives at https://github.com/timholy/HDF5.jl/blob/master/src/plain.jl#L1443

@stevengj
The Julia Language member

I had a related problem: wanted to ccall a varargs function with arguments (Int, Ptr{Void}...) by splicing in the argument list.

There seems to be some disagreement about whether it is portable to assume that varargs are passed in the same way as ordinary arguments, although apparently LLVM assumes (assumed?) this: see here and here, for example.

@Keno Keno was assigned Jun 20, 2013
@ViralBShah ViralBShah removed the feature label Feb 14, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment