# C-Compatible Julia Function

**URL:** <https://discourse.julialang.org/t/c-compatible-julia-function/79458>\
**Category:** General Usage\
**Created:** [April 13, 2022, 8:48pm UTC](https://discourse.julialang.org/t/c-compatible-julia-function/79458 "2022-04-13T20:48:04Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Yinmin\_Liu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yinmin_liu/32/31880_2.png) [@Yinmin\_Liu](https://discourse.julialang.org/u/Yinmin_Liu)\
**Post date:** [April 13, 2022, 8:48pm UTC](https://discourse.julialang.org/t/c-compatible-julia-function/79458/1 "2022-04-13T20:48:04Z")

</div>

Hi,

According to the ccall [doc](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#Creating-C-Compatible-Julia-Function-Pointers), it is possible to pass Julia functions to native C functions. But how should I program my Julia function, when the C function need an input function with void return type and take a pointer as an argument?

The following code demo my question.

 ![image](https://global.discourse-cdn.com/julialang/original/3X/c/6/c6bd4cb73784468f2e3b47470ebfb3e0aeae6541.png)  
The “test” function needs an argument function (\*f). In C, I made a “myFun” function as input. If I want to use the “test” function in Julia, how should I make a Julia version of “myFun”?

Thanks in advance!

---

<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:** [April 13, 2022, 11:17pm UTC](https://discourse.julialang.org/t/c-compatible-julia-function/79458/2 "2022-04-13T23:17:45Z")

</div>

I compiled your C demo as follows:

```julia
gcc -shared -fPIC test.c -o test.so

```

You can invoke your C function via

```julia
using Libdl
lib_handle = Libdl.dlopen(joinpath(pwd(), "test.so"))
test_function_handle = Libdl.dlsym(lib_handle, :test)
myFun_function_handle = Libdl.dlsym(lib_handle, :myFun)

function c_test(a, b, c, f)
    return ccall(test_function_handle , Cvoid, (Cdouble, Cdouble, Ptr{Cdouble}, Ptr{Cvoid}), a, b, c, f)
end

function myFun(a::Cdouble, b::Cdouble, c::Ptr{Cdouble})
    unsafe_store!(c, a * b)
    return nothing
end

function main()
 a = 3.0
 b = 4.0
 c = Ref{Cdouble}(0.0)
 c_myFun = @cfunction(myFun, Cvoid, (Cdouble, Cdouble, Ptr{Cdouble}))
 c_test(a, b, c, c_myFun)

 a = 5.0
 c_test(a, b, c, myFun_function_handle)
end

```

When I invoke this I get the following:

```julia
julia> main()
c before f = 0.000000 
c after f = 12.000000 
c before f = 12.000000 
c after f = 20.000000 

```

---

<div class="post-metadata">

**Author:** ![carstenbauer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/carstenbauer/32/4981_2.png) [@carstenbauer](https://discourse.julialang.org/u/carstenbauer)\
**Post date:** [April 14, 2022, 5:40am UTC](https://discourse.julialang.org/t/c-compatible-julia-function/79458/3 "2022-04-14T05:40:38Z")

</div>

Minor comment: I would make the global handles `const`.

---

<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:** [April 14, 2022, 2:31pm UTC](https://discourse.julialang.org/t/c-compatible-julia-function/79458/4 "2022-04-14T14:31:42Z")

</div>

Yes, but you might need to be careful with this if this is in the global namespace of the module, which may get precompiled. In that case you might need to store a constant `Ref` and perform the handle acquisition in ` __init__ ()`.

The main purpose of the following code is to work around issues of where to load dynamic libraries. In this case, I’m trying to load the dynamic libraries from the current directory while bypassing system configuration issues.

```julia
using Libdl
lib_handle = Libdl.dlopen(joinpath(pwd(), "test.so"))
test_function_handle = Libdl.dlsym(lib_handle, :test)
myFun_function_handle = Libdl.dlsym(lib_handle, :myFun)

```

If the shared libraries are in the expected locations for the system, then this can be much simpler.

---

<div class="post-metadata">

**Author:** ![Yinmin\_Liu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yinmin_liu/32/31880_2.png) [@Yinmin\_Liu](https://discourse.julialang.org/u/Yinmin_Liu)\
**Post date:** [April 14, 2022, 2:45pm UTC](https://discourse.julialang.org/t/c-compatible-julia-function/79458/5 "2022-04-14T14:45:42Z")

</div>

Hi Mark, thanks so much for your reply! It perfectly answered my question. The real project I want to do is using [dumka3.c](http://dumkaland.org/dumka3.c) ODE solver in Julia, and define RHS of the ODEs as Julia functions. Do you think it is a good idea to make a Julia wrapper around the C code? Or, may be directly “translate” the C code to a Julia version is better?

---

<div class="post-metadata">

**Author:** ![Oscar\_Smith](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oscar_smith/32/25343_2.png) [@Oscar\_Smith](https://discourse.julialang.org/u/Oscar_Smith)\
**Post date:** [April 14, 2022, 3:00pm UTC](https://discourse.julialang.org/t/c-compatible-julia-function/79458/6 "2022-04-14T15:00:13Z")

</div>

Why not just use Julia’s ODE solvers which are probably faster anyway?

---

<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:** [April 14, 2022, 3:01pm UTC](https://discourse.julialang.org/t/c-compatible-julia-function/79458/7 "2022-04-14T15:01:06Z")

</div>

This would be a good to coordinate with #sciml and the team behind DifferentialEquations.jl, so I would invite @ChrisRackauckas for comment:  
[https://diffeq.sciml.ai/stable/](https://diffeq.sciml.ai/stable/)

While porting the C code to Julia would be nice, we have excellent infrastructure via [BinaryBuilder.org](http://BinaryBuilder.org) to supply compiled binaries in a cross platform manner. I would consider submitting a recipe to [GitHub - JuliaPackaging/Yggdrasil: Collection of builder repositories for BinaryBuilder.jl](https://github.com/JuliaPackaging/Yggdrasil) if you need it.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [April 14, 2022, 7:20pm UTC](https://discourse.julialang.org/t/c-compatible-julia-function/79458/8 "2022-04-14T19:20:03Z")

</div>

> [@Yinmin\_Liu](#):
>
> The real project I want to do is using [dumka3.c](http://dumkaland.org/dumka3.c) ODE solver in Julia, and define RHS of the ODEs as Julia functions. Do you think it is a good idea to make a Julia wrapper around the C code? Or, may be directly “translate” the C code to a Julia version is better?

dumka is a less stable ROCK with no recurrence relation. Even if that method existed in Julia (which we can add of course), I would still probably recommend ROCK2 or ROCK4 based on the theoretical properties of the method. I don’t think Assyr ever got around to doing a full benchmark between the two (RIP), but I haven’t read anything that would make me prefer dumka to ROCK.

And ROCK2/ROCK4 are implemented:

[https://diffeq.sciml.ai/stable/solvers/ode\_solve/#Stabilized-Explicit-Methods](https://diffeq.sciml.ai/stable/solvers/ode_solve/#Stabilized-Explicit-Methods)

Though if you want to wrap it and put it to the common interface, that could be a cool thing to add to the benchmarks.

---

<div class="post-metadata">

**Author:** ![Yinmin\_Liu](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/yinmin_liu/32/31880_2.png) [@Yinmin\_Liu](https://discourse.julialang.org/u/Yinmin_Liu)\
**Post date:** [April 14, 2022, 7:27pm UTC](https://discourse.julialang.org/t/c-compatible-julia-function/79458/9 "2022-04-14T19:27:14Z")

</div>

Hi Chris, thanks for recommending ROCK, I will definitely try these methods. Also, I will try to wrap dumka to the common Julia ODE interface, I appreciate any hint on how to make a good wrapper.
