Wrapping a C++ library using CxxWrap.jl
ms-vscode-remote.remote-containers
extension (just enter this id in the extension searchbox and click install)add MyGreatCppPackage
julia --color=yes libfoo/build_tarballs.jl --debug --verbose x86_64-linux-gnu
julia --color=yes build_tarballs.jl --verbose --meta-json x86_64-linux-gnu > foo.json
julia build_jll.jl foo.json
#include <jlcxx/jlcxx.hpp>
#include <jlcxx/stl.hpp>
#include <Eigen/Dense>
JLCXX_MODULE define_julia_module(jlcxx::Module& mod)
{
mod.add_type<Eigen::MatrixXd>("MatrixXd");
}
module Eigen
using CxxWrap
@wrapmodule "/workspaces/eigen-wrapper/build/lib/libjleigen"
function __init__()
@initcxx
end
export MatrixXd
end # module
.method("cols", &Eigen::MatrixXd::cols)
.method("rows", &Eigen::MatrixXd::rows)
.method("norm", &Eigen::MatrixXd::norm)
.constructor<int64_t, int64_t>()
// fails
.method("setConstant", &Eigen::MatrixXd::setConstant);
// Cast
.method("setConstant", static_cast<Eigen::MatrixXd& (Eigen::MatrixXd::*)(const double&)>(&Eigen::MatrixXd::setConstant));
// Or use a lambda
.method("setConstant", [](Eigen::MatrixXd& m, double x) { return m.setConstant(x); });
mod.set_override_module(jl_base_module);
mod.method("getindex", [](const Eigen::MatrixXd& m, int_t i, int_t j) { return m(i-1,j-1); });
mod.method("setindex!", [](Eigen::MatrixXd& m, double value, int_t i, int_t j) { m(i-1,j-1) = value; });
mod.unset_override_module();
mod.method("toString", [] (const Eigen::MatrixXd& m)
{
std::stringstream stream;
stream << m;
return stream.str();
});
mod.add_type<Eigen::MatrixXd>("MatrixXd", jlcxx::julia_type("AbstractMatrixXd"))
const AbstractMatrixXd = AbstractMatrix{Float64}
# Complete the interface
Base.size(m::MatrixXd) = (rows(m),cols(m))
Base.IndexStyle(::Type{<:MatrixXd})=IndexCartesian()
namespace jleigen { struct WrapMatrix { template<typename TypeWrapperT> void operator()(TypeWrapperT&& wrapped) { using WrappedT = typename TypeWrapperT::type; using ScalarT = typename WrappedT::Scalar; wrapped.template constructor<Eigen::Index, Eigen::Index>(); wrapped.method("cols", &WrappedT::cols); wrapped.method("rows", &WrappedT::rows); wrapped.method("norm", &WrappedT::norm); wrapped.method("setConstant", static_cast<WrappedT& (WrappedT::*)(const ScalarT&)>(&WrappedT::setConstant)); wrapped.module().set_override_module(jl_base_module); wrapped.module().method("getindex", [](const WrappedT& m, int_t i, int_t j) { return m(i-1,j-1); }); wrapped.module().method("setindex!", [](WrappedT& m, ScalarT value, int_t i, int_t j) { m(i-1,j-1) = value; }); wrapped.module().unset_override_module(); wrapped.module().method("toString", [] (const WrappedT& m) { std::stringstream stream; stream << m; return stream.str(); }); } }; } namespace jlcxx { template<typename T> struct BuildParameterList<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>> { typedef ParameterList<T> type; }; } JLCXX_MODULE define_julia_module(jlcxx::Module& mod) { using jlcxx::Parametric; using jlcxx::TypeVar; mod.add_type<Parametric<TypeVar<1>>>("Matrix", jlcxx::julia_type("AbstractMatrix")) .apply<Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>, Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic>>(jleigen::WrapMatrix()); }
mod.set_const("Dynamic", int_t(Eigen::Dynamic));
mod.add_bits<Eigen::StorageOptions>("StorageOptions", jlcxx::julia_type("CppEnum"));
mod.set_const("ColMajor", Eigen::ColMajor);
mod.set_const("RowMajor", Eigen::RowMajor);
struct ApplyMatrix
{
template<typename T, typename Rows, typename Cols, typename Storage> using apply = Eigen::Matrix<T, Rows::value, Cols::value, Storage::value>;
};
template<typename T, int NRows, int NCols, int S>
struct BuildParameterList<Eigen::Matrix<T, NRows, NCols, S>>
{
using type = ParameterList<T, std::integral_constant<int_t, NRows>, std::integral_constant<int_t, NCols>, std::integral_constant<Eigen::StorageOptions, Eigen::StorageOptions(S)>>;
};
}
JLCXX_MODULE define_julia_module(jlcxx::Module& mod)
{
mod.set_const("Dynamic", int_t(Eigen::Dynamic));
mod.add_bits<Eigen::StorageOptions>("StorageOptions", jlcxx::julia_type("CppEnum"));
mod.set_const("ColMajor", Eigen::ColMajor);
mod.set_const("RowMajor", Eigen::RowMajor);
using jlcxx::Parametric;
using jlcxx::TypeVar;
using jlcxx::ParameterList;
using scalar_types = ParameterList<float, double>;
using sizes = ParameterList<std::integral_constant<int, 2>, std::integral_constant<int, 4>, std::integral_constant<int, Eigen::Dynamic>>;
using storage = ParameterList<std::integral_constant<int, Eigen::ColMajor>, std::integral_constant<int, Eigen::RowMajor>>;
mod.add_type<Parametric<TypeVar<1>, TypeVar<2>, TypeVar<3>, TypeVar<4>>>("Matrix", jlcxx::julia_type("AbstractEigenMatrix"))
.apply_combination<jleigen::ApplyMatrix, scalar_types, sizes, sizes, storage>(jleigen::WrapMatrix());
}
class ExtendedMatrix : public Eigen::Matrix<double,4,4>
{
public:
using base_t = Eigen::Matrix<double,4,4>;
ExtendedMatrix() : base_t() { setConstant(1.0); }
// This constructor allows you to construct ExtendedMatrix from Eigen expressions
template<typename OtherDerived>
ExtendedMatrix(const Eigen::MatrixBase<OtherDerived>& other)
: base_t(other)
{ }
// This method allows you to assign Eigen expressions to ExtendedMatrix
template<typename OtherDerived>
ExtendedMatrix& operator=(const Eigen::MatrixBase <OtherDerived>& other)
{
this->base_t::operator=(other);
return *this;
}
};
namespace jlcxx
{
template<> struct SuperType<jleigen::ExtendedMatrix> { using type = Eigen::Matrix<double,4,4>; };
}
mod.add_type<jleigen::ExtendedMatrix>("ExtendedMatrix", jlcxx::julia_base_type<Eigen::Matrix<double,4,4>>());
#include <jlcxx/smart_pointers.hpp>
mod.method("make_shared", [] ()
{
return std::make_shared<Eigen::MatrixXd>(3,3);
});
mod.method("processvec", [] (const std::vector<Eigen::MatrixXd>& v)
{
for(auto val : v)
{
std::cout << val << std::endl;
}
});