Wrapping C++ struct with libcxxwrap-julia

Hello,
I need some help with wrapping a C++ template struct (from richdem C++ library) into Julia such that it is seamlessly available in Julia to check values of and set values to. This is what I have so far:

  • The template C++ struct:
template <class elev_t>
struct Depression {
  uint32_t pit_cell = NO_VAlLUE;
  uint32_t out_cell = NO_VALUE;
  uint32_t parent = NO_PARENT;
  uint32_t odep = NO_VALUE;
  uint32_t geolink = NO_VALUE;
  elev_t pit_elev = std::numeric_limits<elev_t>::infinity();
  elev_t out_elev = std::numeric_limits<elev_t>::infinity();
  uint32_t lchild = NO_VALUE;
  uint32_t rchild = NO_VALUE;
  bool ocean_parent = false;
  std::vector<uint32_t> ocean_linked;
  uint32_t dep_label = 0;
  uint32_t cell_count = 0;
  double dep_vol = 0;
  double water_vol = 0;
  double total_elevation = 0;
};
  • The wrapper C++ code:
JLCXX_MODULE define_depressions_module(jlcxx::Module &mod)
{
    using jlcxx::Parametric;
    using jlcxx::TypeVar;
    mod.add_type<Parametric<TypeVar<1>>>("Depression", jlcxx::julia_type("Depression", "depressions"))
        .apply<rd::dephier::Depression<float>,
               rd::dephier::Depression<double>>([](auto wrapped)
                                                { using WrappedT = typename decltype(wrapped)::type; });
}
  • Finally the corresponding julia code:
module RichDEM
module depressions
struct Depression{T<:Real}
    pit_cell::UInt32
    out_cell::UInt32
    parent::UInt32
    odep::UInt32
    geolink::UInt32
    pit_elev::T
    out_elev::T
    lchild::UInt32
    rchild::UInt32
    ocean_parent::Bool
    ocean_linked::Vector{UInt32}
    dep_label::UInt32
    cell_count::UInt32
    dep_vol::Float64
    water_vol::Float64
    total_elevation::Float64
end
using CxxWrap

@wrapmodule("/workspaces/richdem/build/lib/libjlrichdem.so", :define_depressions_module)


function __init__()
    @initcxx
end
end #depressions
end

The C++ code compiles alright but when I load the module in Julia, I get the following error:

julia> using RichDEM
[ Info: Precompiling RichDEM [db566695-6f60-45f3-9b37-d3ff769e9aca]
[ Info: Skipping precompilation since __precompile__(false). Importing RichDEM [db566695-6f60-45f3-9b37-d3ff769e9aca].
Warning: Type i already had a mapped type set as Int32 using hash 6253375586064260614 and const-ref indicator 0
Warning: Type a already had a mapped type set as Int8 using hash 4993892634952068459 and const-ref indicator 0
Warning: Type j already had a mapped type set as UInt32 using hash 10485857595211860659 and const-ref indicator 0
C++ exception while wrapping module depressions: invalid subtyping in definition of Depression with supertype Depression
ERROR: LoadError: invalid subtyping in definition of Depression with supertype Depression
Stacktrace:
 [1] register_julia_module
   @ ~/.julia/packages/CxxWrap/IdOJa/src/CxxWrap.jl:405 [inlined]
 [2] readmodule(so_path::String, funcname::Symbol, m::Module, flags::Nothing)
   @ CxxWrap.CxxWrapCore ~/.julia/packages/CxxWrap/IdOJa/src/CxxWrap.jl:734
 [3] wrapmodule(so_path::String, funcname::Symbol, m::Module, flags::Nothing)
   @ CxxWrap.CxxWrapCore ~/.julia/packages/CxxWrap/IdOJa/src/CxxWrap.jl:738
 [4] include
   @ ./Base.jl:419 [inlined]
 [5] _require(pkg::Base.PkgId)
   @ Base ./loading.jl:1367
 [6] _require_prelocked(uuidkey::Base.PkgId)
   @ Base ./loading.jl:1200
 [7] macro expansion
   @ ./loading.jl:1180 [inlined]
 [8] macro expansion
   @ ./lock.jl:223 [inlined]
 [9] require(into::Module, mod::Symbol)
   @ Base ./loading.jl:1144
in expression starting at /workspaces/richdem/wrappers/RichDEM.jl/src/RichDEM.jl:1

not sure how I can resolve this issue. Any help is much appreciated.

We were able to resolve this issue using StlWrappers from libcxxwrap-julia on the C++ side. Here is the code

and the corresponding Julia side

1 Like