I have a C function I’m calling with the signature:
SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ;
(from libsndfile)
the user_data
pointer is passed as an argument to some callbacks that are defined in the SF_VIRTUAL_IO
struct. I’m calling sf_open_virtual
and passing in a pointer to a value that could have varying type, so I have my wrapper defined as:
function sf_open(io::T, mode, sfinfo) where T <: IO
virtio = SF_VIRTUAL_IO(T)
filePtr = ccall((:sf_open_virtual, libsndfile), Ptr{Cvoid},
(Ref{SF_VIRTUAL_IO}, Int32, Ref{SF_INFO}, Ref{T}),
virtio, mode, sfinfo, io)
if filePtr == C_NULL
error("LibSndFile.jl error while opening stream: ", sf_strerror(C_NULL))
end
filePtr
end
I was under the impression that generally when passing pointers to Julia-owned data you should define the argument type as a Ref
, and also that when passing the value to ccall
you can just pass the value and Julia will handle making the Ref
. As I understand it this makes sure that the value remains GC-rooted for the duration of the ccall
. This seems to work fine in 0.7 and 1.0, but in 0.6 I get the error:
error compiling sf_open: ccall: argument type Ref should have an element type, not Ref{T}
I can fix it by making the argument type Ptr{T}
and passing in pointer_from_objref(io)
, and in this case it shouldn’t matter (clearly io
needs to stay GC-rooted anyways because it’ll be referenced later from the callback), but I’m wondering why this doesn’t work as expected.