Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Issue with Julia ccall interface and symbols

Tags:

julia

I'm attemping to use Julia's ccall function to interface with a C library. All the types and pointers are correct, and the below function call successfully returns the correct answer (variable defintion and setup not shown here for brevity).

    ccall((:vDSP_convD, libacc),  Void,
          (Ptr{T}, Int64,  Ptr{T},  Int64,  Ptr{T},  Int64, UInt64, UInt64),
          x_padded, 1, pointer(K, Ksize), -1, result, 1,  Rsize, Ksize)

However, if I wish to generate the function name as a symbol, and then use it as an argument to ccall, it fails.

fname = symbol(string("vDSP_conv", "D"))
ccall((fname , libacc),  Void,
          (Ptr{T}, Int64,  Ptr{T},  Int64,  Ptr{T},  Int64, UInt64, UInt64),
          x_padded, 1, pointer(K, Ksize), -1, result, 1,  Rsize, Ksize)

The error is:

ERROR: LoadError: TypeError: conv: in ccall: first argument not a 
pointer or valid constant expression, expected Ptr{T}, 
got Tuple{Symbol,ASCIIString}

If I print the type of each of these two naming versions, I get

julia> println(typeof(:vDSP_convD))
       Symbol
julia> println(typeof(fname))
       Symbol

Is there a way to get this to work? I'm guessing that I will have to wrap this in a macro or @eval to get this work, but I am curious as to why the above functionality doesn't work as shown?

Any help will be most appreciated!

EDIT

I ended up wrapping this in an @eval block to get it to work; however, I'm still curious as to the backend logic as to why the above syntax doesn't work (why it interprets a symbol as a pointer sometimes, and then not other times)

like image 776
hyperdelia Avatar asked Mar 06 '16 19:03

hyperdelia


1 Answers

ccall is not really a function – it's a syntactic form that is translated to a C function call using the C ABI. To emit a call to a C function, you need to be able to statically resolve the address of the function – that's where this requirement comes from. Note that in both C and Julia you can also call a function using a variable function pointer. In Julia, there are a few ways to get such a pointer, typically by using dlopen and dlsym. What ccall won't do is resolve a function by non-constant name: this is impossible in C (without a building yourself a lookup table); in Julia you can do this, as you've figured out, by using eval – but there is compiler overhead to doing this. That is why ccall won't do this automatically: you don't want to run the risk of accidentally introducing compiler overhead in a loop, for example.

like image 85
StefanKarpinski Avatar answered Dec 29 '22 23:12

StefanKarpinski