[ANN] CClosure.jl: C closures like what C does

Julia has a very powerful @cfunction macro that can make any pure Julia function callable to C. However, it only produces a single function pointer, contrary to modern C libraries where a pair of function pointer and a pass-through context pointer is passed to support arbitrary closures. As a result, @cfunction’s support for closures resorts to LLVM trampolines which is not available on all platforms.

CClosure.jl exports cclosure

cclosure(callable, context_position, ReturnType, (ArgumentTypes...)) -> func_ptr, context

which

  • is regular Julia function call, so local variable and expressions are supported.
  • uses the context pointer to support closures on all platforms that Julia runs.
  • has no extra cost compared to @cfunction AFAICT.

This is an example that uses qsort on Windows

using CClosure
function qsort_c(a, func, ctx)
    @ccall qsort_s(a::Ptr{Cvoid}, length(a)::Csize_t, sizeof(eltype(a))::Csize_t, func::Ptr{Cvoid}, ctx::Ptr{Cvoid})::Cvoid
end
compare(a, b)::Cint = a > b ? +1 : a < b ? -1 : 0
function qsort_log_cclosure(a)
    T = eltype(a)
    log = Tuple{T, T}[]
    func, ctx = cclosure(1, Cint, (Ref{T}, Ref{T})) do a, b
        push!(log, (a, b))
        compare(a, b)
    end
    qsort_c(a, func, ctx)
    log, a
end
qsort_log_cclosure([3,2,1])

For more descriptions check GitHub repo: melonedo/CClosure.jl

4 Likes