# \[Avoid cfunction closure\] GSL root finding problem with function passed as argument

**URL:** <https://discourse.julialang.org/t/avoid-cfunction-closure-gsl-root-finding-problem-with-function-passed-as-argument/85955>\
**Category:** General Usage\
**Tags:** question\
**Created:** [August 18, 2022, 11:31pm UTC](https://discourse.julialang.org/t/avoid-cfunction-closure-gsl-root-finding-problem-with-function-passed-as-argument/85955 "2022-08-18T23:31:08Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Norman](https://avatars.discourse-cdn.com/v4/letter/n/97f17d/32.png) [@Norman](https://discourse.julialang.org/u/Norman)\
**Post date:** [August 18, 2022, 11:31pm UTC](https://discourse.julialang.org/t/avoid-cfunction-closure-gsl-root-finding-problem-with-function-passed-as-argument/85955/1 "2022-08-18T23:31:08Z")

</div>

I have a usage scenario in which the functions that represent the equations for the multidimentional root-finding problem are generated in run time. I use [GSL.jl](https://github.com/JuliaMath/GSL.jl) to solve the root-finding problem, which requires wrapping the functions for the C library.

What I used to do is to make use of the `@cfunction` runtime enclosure. But, now I realize that this is not supported on ARM platforms. The way how I do that is illustrated below. So, I need to somehow circumvent this issue with `@cfunction`. How would that be done?

What I used to do is something like below (what matters the most is just the beginning part). The use of `@cfunction` is giving me error on Apple Silicon.

```julia
ERROR: cfunction: closures are not supported on this platform

```

```julia
using GSL
# For Mac
using LinearAlgebra, OpenBLAS32_jll
LinearAlgebra.BLAS.lbt_forward(OpenBLAS32_jll.libopenblas_path)

function solve!(f!, x0::AbstractArray, maxiter)
    # Do what GSL.@gsl_multiroot_function does to wrap the function
    function _f(x_vec, p, y_vec)
        x = GSL.wrap_gsl_vector(x_vec)
        y = GSL.wrap_gsl_vector(y_vec)
        f!(y, x)
        return Cint(GSL.GSL_SUCCESS)
    end
    # Does not work on ARM !
    cfunc = @cfunction($_f, Cint, (Ptr{GSL.gsl_vector}, Ptr{Cvoid}, Ptr{GSL.gsl_vector}))
    N = length(x0)
    gsl_func = GSL.gsl_multiroot_function(Base.unsafe_convert(Ptr{Cvoid}, cfunc), N, 0)

    # The remaining code solves the root-finding problem
    vinit = GSL.vector_alloc(N)
    solver = GSL.multiroot_fsolver_alloc(GSL.gsl_multiroot_fsolver_hybrids, N)

    for (i, v) in enumerate(x0)
        v = convert(Cdouble, v)
        GSL.vector_set(vinit, i-1, v)
    end

    GSL.multiroot_fsolver_set(solver, gsl_func, vinit)

    iter = 0
    while iter < maxiter
        iter += 1
        status = GSL.multiroot_fsolver_iterate(solver)
    end
    x = GSL.multiroot_fsolver_root(solver)
    # Copy the solution
    sol = Vector{Float64}(unsafe_wrap(Array{Cdouble}, GSL.vector_ptr(x, 0), N))
    GSL.multiroot_fsolver_free(solver)
    GSL.vector_free(vinit)
    return sol
end

# The function for the actual scenario is only known in run time
function f!(x::Array{Float64}, out::Array{Float64})
    out[1:5] = (x .- collect(1.0:5.0)).^2
end

x0 = [1.0, 5.0, 2.0, 1.5, -1.0]

solve!(f!, x0, 5)

```

Thank you for any advice!

---

<div class="post-metadata">

**Author:** ![Norman](https://avatars.discourse-cdn.com/v4/letter/n/97f17d/32.png) [@Norman](https://discourse.julialang.org/u/Norman)\
**Post date:** [August 19, 2022, 7:30am UTC](https://discourse.julialang.org/t/avoid-cfunction-closure-gsl-root-finding-problem-with-function-passed-as-argument/85955/2 "2022-08-19T07:30:25Z")

</div>

OK. I figured it out by myself after studying this amazing blog: [Passing Julia Callback Functions to C (julialang.org)](https://julialang.org/blog/2013/05/callback/)

The trick is to make use of the parameter argument available for GSL functions, which avoids the need for using any cfunction closure.
