Passing a function over vectors as an argument to ccall

It does not work for me.

Here’s the initial setup.

julia> write("libDummy.c", """
       #include<stddef.h>

       #define EXPORT_C

       EXPORT_C double apply_fun_simple(double (*fun)(double*), double* x) {
           return (*fun)(x);
       }

       EXPORT_C double apply_fun_mixed(double (*fun)(double*, size_t), double* x, size_t len) {
           return (*fun)(x,len);
       }
       """)
250

julia> run(`gcc -shared -fpic libDummy.c -o libDummy.so`)
Process(`gcc -shared -fpic libDummy.c -o libDummy.so`, ProcessExited(0))

Here’s my closest approximation of what you are trying to do.

julia> using Libdl

julia> Libdl.dlopen("./libDummy.so")
Ptr{Nothing} @0x00000000082313a0

julia> const libDummy ="./libDummy.so"
"./libDummy.so"

julia> function foo(x::Vector{Float64})::Float64
           return sum(x)
       end
foo (generic function with 1 method)

julia> x = Vector{Float64}([1,2,3])
3-element Vector{Float64}:
 1.0
 2.0
 3.0

julia> foo_c = @cfunction(foo, Float64, (Ref{Float64},))
Ptr{Nothing} @0x00007414cdc86290

julia> r_foo = @ccall libDummy.apply_fun_simple(foo_c::Ptr{Cvoid}, x::Ref{Float64})::Float64
ERROR: MethodError: no method matching foo(::Float64)

Closest candidates are:
  foo(::Vector{Float64})
   @ Main REPL[7]:1

julia> function bar(x::Vector{Float64}, s::UInt64)::Float64
           return sum(x[i] for i in 1:s)
       end
bar (generic function with 1 method)

julia> x = Vector{Float64}([1,2,3])
3-element Vector{Float64}:
 1.0
 2.0
 3.0

julia> s::UInt64 = length(x)
3

julia> bar_c = @cfunction(bar, Float64, (Ref{Float64},UInt64,))
Ptr{Nothing} @0x00007b2ed3309ac0

julia> r_bar = @ccall libDummy.apply_fun_mixed(bar_c::Ptr{Cvoid}, x::Ref{Float64}, s::UInt64)::Float64
ERROR: MethodError: no method matching bar(::Float64, ::UInt64)

Closest candidates are:
  bar(::Vector{Float64}, ::UInt64)
   @ Main REPL[14]:1

The following does work for me.

julia> foo_c = @cfunction(foo, Float64, (Vector{Float64},))
Ptr{Nothing} @0x00007b2ed330c1c0

julia> r_foo = @ccall libDummy.apply_fun_simple(foo_c::Ptr{Cvoid}, x::Vector{Float64})::Float64
6.0

julia> bar_c = @cfunction(bar, Float64, (Vector{Float64},UInt64,))
Ptr{Nothing} @0x00007b2ed330c980

julia> r_bar = @ccall libDummy.apply_fun_mixed(bar_c::Ptr{Cvoid}, x::Vector{Float64}, s::UInt64)::Float64
6.0

We’re really abusing pointers though in doing this though.

2 Likes