I want to use CxxWrap.jl
to create a Julia wrapper for a C++ library.
On the Julia side, I want to dispatch on the type of my arguments.
But when using CxxWrap
, the Julia side only seems to know about the static return type (the one in the signature of the C++ function) and not about the dynamic return type (which can be a subtype of the static return type).
Is there a way to expose the dynamic return type to Julia?
Here’s the simplest MWE I could come up with:
// polymorphism.cpp
#include <jlcxx/jlcxx.hpp>
#include <iostream>
struct Parent {
virtual std::string name() const { return "Parent"; }
virtual ~Parent() = default;
};
struct DerivedA : public Parent {
std::string name() const override { return "DerivedA"; }
};
struct DerivedB : public Parent {
std::string name() const override { return "DerivedB"; }
};
Parent* make_a() { return new DerivedA(); }
Parent* make_b() { return new DerivedB(); }
JLCXX_MODULE define_julia_module(jlcxx::Module& mod)
{
mod.add_type<Parent>("Parent")
.method("name", &Parent::name);
mod.add_type<DerivedA>("DerivedA", jlcxx::julia_base_type<Parent>())
.method("name", &DerivedA::name);
mod.add_type<DerivedB>("DerivedB", jlcxx::julia_base_type<Parent>())
.method("name", &DerivedB::name);
mod.method("make_a", &make_a);
mod.method("make_b", &make_b);
}
and on the Julia side
# test.jl
using CxxWrap
@wrapmodule(() -> joinpath(@__DIR__, "build", "libpolymorphism"))
function __init__()
@initcxx
end
a = make_a()
b = make_b()
println("Type of a: ", typeof(a)) # CxxPtr{Parent}
println("Type of b: ", typeof(b)) # CxxPtr{Parent}
println("Name from a.name(): ", name(a)) # DerivedA
println("Name from b.name(): ", name(b)) # DerivedB
Ideally, I want typeof(a)
to print CxxPtr{DerivedA}
(and similarly for b
).
Here’s the cmake file, in case you want to build the MWE yourself:
cmake_minimum_required(VERSION 3.10)
project(CxxWrapPolymorphicMWE)
find_package(JlCxx REQUIRED)
add_library(polymorphism SHARED src/polymorphism.cpp)
target_link_libraries(polymorphism PRIVATE JlCxx::cxxwrap_julia)