Pointer to Julia function in ccall


#1

Is there a way to use pointer to Julia function in ccall? Following the documentation https://docs.julialang.org/en/stable/manual/calling-c-and-fortran-code/ the kernel (Julia 0.5.1) crashes (and there is no alias for C void in Julia). Obviously, the example from documentation works.

# Julia C-like function void(__stdcall*)(float progress);
function clbProgress(f::Float32)
  print(f)  
  return Void
end

function progress(fnc::Ptr{Void}, progress::Float32)
  fnc != Ptr{Void}(0) && ccall(fnc, Void, (Float32, ), progress)
end

const fnc_c = cfunction(clbProgress, Void, (Ref{Cfloat})) # here the 0.5.1 kernel crashes
progress(fnc_c, 0.1f0)

Note: using a C-imported function pointer works.


#2

The crash is due to the fact that the list of input types should be a tuple and a one-element tuple is indicated by (x,). In addition, you have to indicate the type of the return value, which is Type{Void}, not Void itself:

function clbProgress(f::Float32)
  print(f)
  return Void
end

function progress(fnc::Ptr{Void}, progress::Float32)
  fnc != C_NULL && ccall(fnc, Type{Void}, (Float32, ), progress)
end

const fnc_c = cfunction(clbProgress, Type{Void}, (Ref{Cfloat},))
progress(fnc_c, 0.1f0)

#3

thanks for the correcting the code, now it compiles fine, but it doesn’t give correct results… any idea?

julia> progress(fnc_c, 0.1f0)
-8.103731f22
Void

julia> p = 1.1f0
1.1f0

julia> ccall(fnc_c, Type{Void}, (Float32, ), p)
0.0
Void

# just check here
julia> clbProgress(2.2f0)
2.2
Void

#4

Yes, coherently use either Cfloat or Ref{Cfloat} as input type:

function clbProgress(f::Float32)
  print(f)
  return Void
end

function progress(fnc::Ptr{Void}, progress::Float32)
  fnc != Ptr{Void}(0) && ccall(fnc, Type{Void}, (Cfloat, ), progress)
end

const fnc_c = cfunction(clbProgress, Type{Void}, (Cfloat,))
progress(fnc_c, 0.1f0)

I don’t know why you wanted to use a Ref before, so here I went with Cfloat.


#5

thanks again, good point! I took the Ref from docs; and yes it is a pointer to the value, not the value itself i want to pass!