Passing an array of a C++ class to julia (CxxWrap)

Hi,

I’ve been wrapping a C++ library with C++ wrap, and some of the methods in it return vectors, either of simple items like floats, and ints, or sometimes vectors of classes.

I’ve come up with a way to give a std::vector to julia by doing the following:

.method("get_fw_nodes", [](SequenceGraph& sg, sgNodeID_t n) {
                std::vector<sgNodeID_t> fw_nodes = sg.get_fw_nodes(n);
                auto *nodes = new sgNodeID_t[fw_nodes.size()];
                std::copy(fw_nodes.begin(), fw_nodes.end(), nodes);
                auto jlarr = jlcxx::make_julia_array(nodes, fw_nodes.size());
                return jlarr;
            })

So I call the method, get the vector, allocate a new array, copy vector contents to the array, wrap that up in an ArrayRef and pass that to julia. This works great for this case as sgNodeID_t is just int64_t.
The use of a new without a paired delete scares me, but I’m trusting julia gc to take care of that, as I believe jccxx::make_julia_array ensures the resulting Array is owned by julia and so should be gc’d.

I’d like to do something similar, passing an array of a C++ class. The class is wrapped in CxxWrap too:

mod.add_type<Link>("Link")
            .constructor()
            .constructor<sgNodeID_t, sgNodeID_t, int32_t>();

However trying to do something like this:

.method("get_fw_links", [](SequenceGraph& sg, sgNodeID_t n){
                std::vector<Link> fw_links = sg.get_fw_links(n);
                auto *links = new Link[fw_links.size()];
                std::copy(fw_links.begin(), fw_links.end(), links);
                auto jlarr = jlcxx::make_julia_array(links, fw_links.size());
                return jlarr;
            })

Doesn’t work. Is it at all possible using CxxWrap and any other julia c/c++ interfacing to pass to julia an array of C++ objects (which are themselves CxxWrapped)? I know an alternative route is to wrap std::vector.

1 Like

Or just allocate the vector on the julia side and pass it to get_fw_links to be initialized (since You already the size?)

std::vector stores classes contiguously, whereas julia array’s don’t nessecerily do that. Presumably even if I allocated on the Julia side, say Vector{LinkRef} or Vector{LinkAllocated}, I would need some way on the C++ side, to box up each Link object so as it can be given to those julia arrays and not eliminated by C++ destructors?

I’m not sure I understand why you want to copy the data in the first place.
Please take a look here: LCIO_Julia_Wrapper/MCParticle.icc at main · jstrube/LCIO_Julia_Wrapper · GitHub
This wraps a method that returns a vector of objects. MCParticleVec is just a typedef to an std::vector<MCParticle>. The C++ API is here: http://lcio.desy.de/v02-09/doc/doxygen_api/html/classEVENT_1_1MCParticle.html
Then I just wrap at and size of the std::vector and make an iterator on the Julia side.
Does that help?

This approach (wrapping at and length as getindex and length and writing an iterator in Julia) worked out for me as well, but I would prefer a solution which could handle all std::vector’s in one go - preferably built-in to CxxWrap, similar to functionality in Cxx.

But in any case - I am very grateful for CxxWrap and the solution posted here.