Pass a ref to tuple to ccall

I am calling an external C function that takes as an argument a pointer to an array of 4 chars and fills it with values.
Myy initial attempt at a Julia wrapper was:

@inline function XXH32toCanonical(h::UInt32)::NTuple{4,UInt8}
   c = NTuple{4,UInt8}((0,0,0,0))
   ccall((:XXH32_canonicalFromHash, libxxhash), Cvoid,
         (Ptr{NTuple{4,Cuchar}}, Cuint), Ref(c), h)
   return c
end

This does not produce any errors, but does not work - the returned a tuple of zeros. This is probably due to the immutability of tuples.

I tried various “tricks”, including unsafe_convert which ended up raising a runtime ERROR: ReadOnlyMemoryError()
What is the correct way of send a mutable 4 byte array to a C function?

You can’t expect c to change when it is immutable. Try

c = Ref(NTuple{4,UInt8}((0,0,0,0))
ccall(...)
return c[]

(https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#Passing-Pointers-for-Modifying-Inputs-1)

2 Likes