GC error / sefgault in a simple C wrapper

Krastanov
Mon, 17 Mar 2025 00:37:26 +0000
General Usage

I am attempting to make a julia wrapper for a C library. The C library is already available as a jll. I was attempting to use Clang.jl to make the wrapper, but whatever I am doing seems to be causing segfaults on garbage collection.

Here is what Clang.jl generates for me (only the minimal amount of bindings to show the problem) and the segfault it causes:

I am wrapping the graph theory library igraph, in particular I am creating an empty struct igraph_t representing a graph, then initializing it to be the “4 nodes and 0 edges” graph by using igraph_empty.

# bindings generated by Clang.jl and selectively copied here by me
using igraph_jll

using CEnum

@cenum igraph_error_type_t::UInt32 begin
    IGRAPH_SUCCESS = 0
    IGRAPH_FAILURE = 1
    # ... skip a bunch of other options
end

const igraph_error_t = igraph_error_type_t

const igraph_integer_t = Int64

const igraph_bool_t = Bool

mutable struct igraph_i_property_cache_t end

mutable struct igraph_vector_int_t
    stor_begin::Ptr{igraph_integer_t}
    stor_end::Ptr{igraph_integer_t}
    _end::Ptr{igraph_integer_t}
    igraph_vector_int_t() = new()
end

mutable struct igraph_s
    n::igraph_integer_t
    directed::igraph_bool_t
    from::igraph_vector_int_t
    to::igraph_vector_int_t
    oi::igraph_vector_int_t
    ii::igraph_vector_int_t
    os::igraph_vector_int_t
    is::igraph_vector_int_t
    attr::Ptr{Cvoid}
    cache::Ptr{igraph_i_property_cache_t}
    igraph_s() = new()
end

const igraph_t = igraph_s

function igraph_empty(graph, n, directed)
    ccall((:igraph_empty, libigraph), igraph_error_t, (Ptr{igraph_t}, igraph_integer_t, igraph_bool_t), graph, n, directed)
end

##
# simple usage example that segfaults

a = igraph_s();
igraph_empty(pointer_from_objref(a), 4, false)
GC.gc() # segfaults

Any idea where I am going wrong? Introspecting some of the properties of a like a.n and a.directed gives me the expected values, but looking at a.to which should be storing the destination for each edge causes a segfault.

6 posts - 3 participants