# Passing a function over vectors as an argument to ccall

**URL:** <https://discourse.julialang.org/t/passing-a-function-over-vectors-as-an-argument-to-ccall/114487>\
**Category:** General Usage\
**Tags:** ccall\
**Created:** [May 20, 2024, 11:13pm UTC](https://discourse.julialang.org/t/passing-a-function-over-vectors-as-an-argument-to-ccall/114487 "2024-05-20T23:13:24Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![brunompacheco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brunompacheco/32/209375_2.png) [@brunompacheco](https://discourse.julialang.org/u/brunompacheco)\
**Post date:** [May 20, 2024, 11:13pm UTC](https://discourse.julialang.org/t/passing-a-function-over-vectors-as-an-argument-to-ccall/114487/1 "2024-05-20T23:13:24Z")

</div>

I am not being able to properly pass a julia-defined function that takes vector and scalar values to C-defined functions.

I have two functions in C

```julia
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);
}

```

and my julia code is

```julia
using Libdl

Libdl.dlopen("/path/to/libDummy.so")

# SIMPLE
function foo(x::Vector{Float64})::Float64
    return sum(x)
end
x = Vector{Float64}([1,2,3])

foo_c = @cfunction(foo, Float64, (Ref{Float64},))

r_foo = @ccall :libDummy.apply_fun_simple(foo_c::Ptr{Cvoid}, x::Ref{Float64})::Float64
println(r_foo)

# MIXED
function bar(x::Vector{Float64}, s::UInt64)::Float64
    return sum(x[i] for i in 1:s)
end
x = Vector{Float64}([1,2,3])
s::UInt64 = length(x)

bar_c = @cfunction(bar, Float64, (Ref{Float64},UInt64,))

r_bar = @ccall :libDummy.apply_fun_mixed(bar_c::Ptr{Cvoid}, x::Ref{Float64}, s::UInt64)::Float64
println(r_bar)

```

but I get  
`ERROR: LoadError: MethodError: no method matching bar(::Float64, ::UInt64)`  
at the ccall macro.

I have tried different types for both variables, but I’ve had no success. Note that the call to `apply_fun_simple` works, but the call to `apply_fun_mixed` doesn’t!

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 21, 2024, 1:12am UTC](https://discourse.julialang.org/t/passing-a-function-over-vectors-as-an-argument-to-ccall/114487/2 "2024-05-21T01:12:23Z")

</div>

> [@brunompacheco](#):
>
> Note that the call to `apply_fun_simple` works

It does not work for me.

Here’s the initial setup.

```julia-repl
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-repl
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-repl
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.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 21, 2024, 1:23am UTC](https://discourse.julialang.org/t/passing-a-function-over-vectors-as-an-argument-to-ccall/114487/3 "2024-05-21T01:23:11Z")

</div>

Let’s say you actually wanted Julia functions that match the C function pointers.

```julia
function foo(p::Ptr{Float64})::Float64
    return sum(unsafe_wrap(Vector{Float64}, p, 3; own = false))
end
foo_c = @cfunction(foo, Float64, (Ptr{Float64},))
r_foo = @ccall libDummy.apply_fun_simple(foo_c::Ptr{Cvoid}, x::Ptr{Float64})::Float64
println(r_foo)

function bar(p::Ptr{Float64}, s::UInt64)::Float64
    return sum(unsafe_load(p, i) for i in 1:s)
end
bar_c = @cfunction(bar, Float64, (Ptr{Float64},UInt64,))
r_bar = @ccall libDummy.apply_fun_mixed(bar_c::Ptr{Cvoid}, x::Ptr{Float64}, s::Csize_t)::Float64
println(r_bar)

```

We could even be explicit about what we are doing.

```julia
function foo(p::Ptr{Cdouble})::Cdouble
    return sum(unsafe_wrap(Vector{Cdouble}, p, 3; own = false))
end
foo_c = @cfunction(foo, Cdouble, (Ptr{Cdouble},))
r_foo = @ccall libDummy.apply_fun_simple(foo_c::Ptr{Cvoid}, x::Ptr{Cdouble})::Cdouble
println(r_foo)

function bar(p::Ptr{Cdouble}, s::Csize_t)::Cdouble
    return sum(unsafe_load(p, i) for i in 1:s)
end
bar_c = @cfunction(bar, Cdouble, (Ptr{Cdouble}, Csize_t,))
r_bar = @ccall libDummy.apply_fun_mixed(bar_c::Ptr{Cvoid}, x::Ptr{Cdouble}, s::Csize_t)::Cdouble
println(r_bar)

```

Note that you can call your C function pointers directly as well.

```julia-repl
julia> @ccall $foo_c(x::Ptr{Cdouble})::Cdouble
6.0

julia> @ccall $bar_c(x::Ptr{Cdouble}, s::Csize_t)::Cdouble
6.0

```

---

<div class="post-metadata">

**Author:** ![brunompacheco](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brunompacheco/32/209375_2.png) [@brunompacheco](https://discourse.julialang.org/u/brunompacheco)\
**Post date:** [May 21, 2024, 1:55pm UTC](https://discourse.julialang.org/t/passing-a-function-over-vectors-as-an-argument-to-ccall/114487/4 "2024-05-21T13:55:37Z")

</div>

Thank you!

I marked the first reply as the solution because it is the one that actually solved the problem I posted.

However, one thing that I forgot to mention is that the functions should work with arrays defined inside the C code, which was the original reason why I swapped Vector{Float64} to Ptr{Float64} in the cfunction macro. Wrapping the julia function with the `unsafe_wrap` operation perfectly solved my original problem. So thank you very much for your second reply 🙂

I am still struggling a bit with the double\* to Vector{Float64} conversions. It seems that there is some difference between passing pointers (`double* p`) and arrays (`double p[s]`) to my julia function. But I was able to find some workarounds.
