Ccall: how to wrap call-by-reference C functions?

Hi

I’m trying to wrap a C library, and I can’t figure out how references are handled in ccall.

Here is my study case: I have a simple C file, called jlptrtest.c, consisting of just this:

void put_7( int *i ) {
   *i = 7;
}

I’ve compiled it with cc jlptrtest.c -fPIC -shared -o libptrtest.so and am now trying to use it from Julia. I want to access the value 7. I’ve tried

a = 13
ccall( (:put_7, "libptrtest"), Cvoid, (Ref{Cint},), a )
println(a)

and it prints 13, not 7. Which type should a have, and how do I have to write the ccall so that I can get my 7?

Thanks in advance.

Simon

The one you declare you’re passing to the C function, Ref{Cint}. Note that Cint is an alias for Int32, but integer literals on a 64-bit Julia are Int64

julia> a = Ref{Cint}(13)
Base.RefValue{Int32}(13)

julia> ccall((:put_7, "./libptrtest.so"), Cvoid, (Ref{Cint},), a)

julia> a
Base.RefValue{Int32}(7)

julia> a[]
7

For reference, see the relevant section of the manual: Passing Pointers for Modifying Inputs

2 Likes

ccall( (:put_7, "libptrtest"), Cvoid, (Ref{Cint},), a )

What happened here was

  1. a was Base.cconvert-ed to a tmp_var of type Ref{Cint}
  2. the put_7 function in your c library edited the value of tmp_var
  3. a is left untouched

The fix is to define a as a Ref: a_ref = Ref{Cint}(13)

4 Likes

Thanks a lot to both of you. I though I had tried that, too, but obviously I hadn’t. Now it works.

2 Likes