Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 31 additions & 5 deletions gtwrap/pybind_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ class PybindWrapper:
Class to generate binding code for Pybind11 specifically.
"""

ARG_POLICY_SUPPORT = """
#include <type_traits>

namespace gtwrap {
namespace internal {

template <typename T>
struct PyArgPolicy {
static pybind11::arg make(const char* name) { return pybind11::arg(name); }
};

template <typename T>
pybind11::arg py_arg(const char* name) {
return PyArgPolicy<typename std::decay<T>::type>::make(name);
}

} // namespace internal
} // namespace gtwrap
"""

def __init__(self,
module_name,
top_module_namespaces='',
Expand Down Expand Up @@ -70,8 +90,11 @@ def _py_args_names(self, args):
default = ' = {arg.default}'.format(arg=arg)
else:
default = ''
argument = 'py::arg("{name}"){default}'.format(
name=arg.name, default='{0}'.format(default))
argument = (
'gtwrap::internal::py_arg<{ctype}>("{name}"){default}'
).format(ctype=arg.ctype.to_cpp(),
name=arg.name,
default='{0}'.format(default))
py_args.append(argument)
return ", " + ", ".join(py_args)
else:
Expand Down Expand Up @@ -251,12 +274,13 @@ def _wrap_method(self,
method,
(parser.StaticMethod, instantiator.InstantiatedStaticMethod))
return_void = method.return_type.is_void()
return_ref = getattr(
getattr(method.return_type, 'type1', None), 'is_ref', False)
return_type = getattr(method.return_type, 'type1', None)
return_ref = getattr(return_type, 'is_ref', False)
return_const = getattr(return_type, 'is_const', False)

# For methods returning const T&, use reference_internal policy
# to avoid unnecessary copies and keep the returned reference alive.
if return_ref and is_method:
if return_ref and return_const and is_method:
lambda_ret = ' -> const auto&'
ref_policy = ', py::return_value_policy::reference_internal'
else:
Expand Down Expand Up @@ -752,6 +776,8 @@ def wrap_file(self, content, module_name=None, submodules=None):
module_def = "void {0}(py::module_ &m_)".format(module_name)
submodules = []

includes += self.ARG_POLICY_SUPPORT

return self.module_template.format(
module_def=module_def,
module_name=module_name,
Expand Down
98 changes: 58 additions & 40 deletions tests/expected/python/class_pybind.cpp

Large diffs are not rendered by default.

26 changes: 22 additions & 4 deletions tests/expected/python/enum_pybind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@
#include "gtsam/nonlinear/utilities.h" // for RedirectCout.


#include <type_traits>

namespace gtwrap {
namespace internal {

template <typename T>
struct PyArgPolicy {
static pybind11::arg make(const char* name) { return pybind11::arg(name); }
};

template <typename T>
pybind11::arg py_arg(const char* name) {
return PyArgPolicy<typename std::decay<T>::type>::make(name);
}

} // namespace internal
} // namespace gtwrap




Expand All @@ -23,8 +41,8 @@ PYBIND11_MODULE(enum_py, m_) {

py::class_<Pet, std::shared_ptr<Pet>> pet(m_, "Pet");
pet
.def(py::init<const string&, Pet::Kind>(), py::arg("name"), py::arg("type"))
.def("setColor",[](Pet* self, const Color& color){ self->setColor(color);}, py::arg("color"))
.def(py::init<const string&, Pet::Kind>(), gtwrap::internal::py_arg<const string&>("name"), gtwrap::internal::py_arg<Pet::Kind>("type"))
.def("setColor",[](Pet* self, const Color& color){ self->setColor(color);}, gtwrap::internal::py_arg<const Color&>("color"))
.def("getColor",[](Pet* self){return self->getColor();})
.def_readwrite("name", &Pet::name)
.def_readwrite("type", &Pet::type);
Expand Down Expand Up @@ -67,8 +85,8 @@ PYBIND11_MODULE(enum_py, m_) {

py::class_<gtsam::Optimizer<gtsam::GaussNewtonParams>, std::shared_ptr<gtsam::Optimizer<gtsam::GaussNewtonParams>>> optimizergaussnewtonparams(m_gtsam, "OptimizerGaussNewtonParams");
optimizergaussnewtonparams
.def(py::init<const Optimizer<gtsam::GaussNewtonParams>::Verbosity&>(), py::arg("verbosity"))
.def("setVerbosity",[](gtsam::Optimizer<gtsam::GaussNewtonParams>* self, const Optimizer<gtsam::GaussNewtonParams>::Verbosity value){ self->setVerbosity(value);}, py::arg("value"))
.def(py::init<const Optimizer<gtsam::GaussNewtonParams>::Verbosity&>(), gtwrap::internal::py_arg<const Optimizer<gtsam::GaussNewtonParams>::Verbosity&>("verbosity"))
.def("setVerbosity",[](gtsam::Optimizer<gtsam::GaussNewtonParams>* self, const Optimizer<gtsam::GaussNewtonParams>::Verbosity value){ self->setVerbosity(value);}, gtwrap::internal::py_arg<const Optimizer<gtsam::GaussNewtonParams>::Verbosity>("value"))
.def("getVerbosity",[](gtsam::Optimizer<gtsam::GaussNewtonParams>* self){return self->getVerbosity();})
.def("getVerbosity",[](gtsam::Optimizer<gtsam::GaussNewtonParams>* self){return self->getVerbosity();});

Expand Down
58 changes: 38 additions & 20 deletions tests/expected/python/functions_pybind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@
#include "gtsam/nonlinear/utilities.h" // for RedirectCout.


#include <type_traits>

namespace gtwrap {
namespace internal {

template <typename T>
struct PyArgPolicy {
static pybind11::arg make(const char* name) { return pybind11::arg(name); }
};

template <typename T>
pybind11::arg py_arg(const char* name) {
return PyArgPolicy<typename std::decay<T>::type>::make(name);
}

} // namespace internal
} // namespace gtwrap




Expand All @@ -16,27 +34,27 @@ PYBIND11_MODULE(functions_py, m_) {
m_.doc() = "pybind11 wrapper of functions_py";


m_.def("load2D",[](string filename, std::shared_ptr<Test> model, int maxID, bool addNoise, bool smart){return ::load2D(filename, model, maxID, addNoise, smart);}, py::arg("filename"), py::arg("model"), py::arg("maxID"), py::arg("addNoise"), py::arg("smart"));
m_.def("load2D",[](string filename, const std::shared_ptr<gtsam::noiseModel::Diagonal> model, int maxID, bool addNoise, bool smart){return ::load2D(filename, model, maxID, addNoise, smart);}, py::arg("filename"), py::arg("model"), py::arg("maxID"), py::arg("addNoise"), py::arg("smart"));
m_.def("load2D",[](string filename, gtsam::noiseModel::Diagonal* model){return ::load2D(filename, model);}, py::arg("filename"), py::arg("model"));
m_.def("load2D",[](string filename, std::shared_ptr<Test> model, int maxID, bool addNoise, bool smart){return ::load2D(filename, model, maxID, addNoise, smart);}, gtwrap::internal::py_arg<string>("filename"), gtwrap::internal::py_arg<std::shared_ptr<Test>>("model"), gtwrap::internal::py_arg<int>("maxID"), gtwrap::internal::py_arg<bool>("addNoise"), gtwrap::internal::py_arg<bool>("smart"));
m_.def("load2D",[](string filename, const std::shared_ptr<gtsam::noiseModel::Diagonal> model, int maxID, bool addNoise, bool smart){return ::load2D(filename, model, maxID, addNoise, smart);}, gtwrap::internal::py_arg<string>("filename"), gtwrap::internal::py_arg<const std::shared_ptr<gtsam::noiseModel::Diagonal>>("model"), gtwrap::internal::py_arg<int>("maxID"), gtwrap::internal::py_arg<bool>("addNoise"), gtwrap::internal::py_arg<bool>("smart"));
m_.def("load2D",[](string filename, gtsam::noiseModel::Diagonal* model){return ::load2D(filename, model);}, gtwrap::internal::py_arg<string>("filename"), gtwrap::internal::py_arg<gtsam::noiseModel::Diagonal*>("model"));
m_.def("aGlobalFunction",[](){return ::aGlobalFunction();});
m_.def("overloadedGlobalFunction",[](int a){return ::overloadedGlobalFunction(a);}, py::arg("a"));
m_.def("overloadedGlobalFunction",[](int a, double b){return ::overloadedGlobalFunction(a, b);}, py::arg("a"), py::arg("b"));
m_.def("MultiTemplatedFunctionStringSize_tDouble",[](const string& x, size_t y){return ::MultiTemplatedFunction<string,size_t,double>(x, y);}, py::arg("x"), py::arg("y"));
m_.def("MultiTemplatedFunctionDoubleSize_tDouble",[](const double& x, size_t y){return ::MultiTemplatedFunction<double,size_t,double>(x, y);}, py::arg("x"), py::arg("y"));
m_.def("DefaultFuncInt",[](int a, int b){ ::DefaultFuncInt(a, b);}, py::arg("a") = 123, py::arg("b") = 0);
m_.def("DefaultFuncString",[](const string& s, const string& name){ ::DefaultFuncString(s, name);}, py::arg("s") = "hello", py::arg("name") = "");
m_.def("DefaultFuncObj",[](const gtsam::KeyFormatter& keyFormatter){ ::DefaultFuncObj(keyFormatter);}, py::arg("keyFormatter") = gtsam::DefaultKeyFormatter);
m_.def("DefaultFuncZero",[](int a, int b, double c, int d, bool e){ ::DefaultFuncZero(a, b, c, d, e);}, py::arg("a"), py::arg("b"), py::arg("c") = 0.0, py::arg("d") = 0, py::arg("e") = false);
m_.def("DefaultFuncVector",[](const std::vector<int>& i, const std::vector<string>& s){ ::DefaultFuncVector(i, s);}, py::arg("i") = {1, 2, 3}, py::arg("s") = {"borglab", "gtsam"});
m_.def("setPose",[](const gtsam::Pose3& pose){ ::setPose(pose);}, py::arg("pose") = gtsam::Pose3());
m_.def("EliminateDiscrete",[](const gtsam::DiscreteFactorGraph& factors, const gtsam::Ordering& frontalKeys){return ::EliminateDiscrete(factors, frontalKeys);}, py::arg("factors"), py::arg("frontalKeys"));
m_.def("triangulatePoint3Cal3_S2",[](const gtsam::Pose3Vector& poses, std::shared_ptr<gtsam::Cal3_S2> sharedCal, const gtsam::Point2Vector& measurements, double rank_tol, bool optimize, const gtsam::SharedNoiseModel& model){return ::triangulatePoint3<gtsam::Cal3_S2>(poses, sharedCal, measurements, rank_tol, optimize, model);}, py::arg("poses"), py::arg("sharedCal"), py::arg("measurements"), py::arg("rank_tol"), py::arg("optimize"), py::arg("model") = nullptr);
m_.def("FindKarcherMeanPoint3",[](const std::vector<gtsam::Point3>& elements){return ::FindKarcherMean<gtsam::Point3>(elements);}, py::arg("elements"));
m_.def("FindKarcherMeanSO3",[](const std::vector<gtsam::SO3>& elements){return ::FindKarcherMean<gtsam::SO3>(elements);}, py::arg("elements"));
m_.def("FindKarcherMeanSO4",[](const std::vector<gtsam::SO4>& elements){return ::FindKarcherMean<gtsam::SO4>(elements);}, py::arg("elements"));
m_.def("FindKarcherMeanPose3",[](const std::vector<gtsam::Pose3>& elements){return ::FindKarcherMean<gtsam::Pose3>(elements);}, py::arg("elements"));
m_.def("TemplatedFunctionRot3",[](const gtsam::Rot3& t){ ::TemplatedFunction<gtsam::Rot3>(t);}, py::arg("t"));
m_.def("overloadedGlobalFunction",[](int a){return ::overloadedGlobalFunction(a);}, gtwrap::internal::py_arg<int>("a"));
m_.def("overloadedGlobalFunction",[](int a, double b){return ::overloadedGlobalFunction(a, b);}, gtwrap::internal::py_arg<int>("a"), gtwrap::internal::py_arg<double>("b"));
m_.def("MultiTemplatedFunctionStringSize_tDouble",[](const string& x, size_t y){return ::MultiTemplatedFunction<string,size_t,double>(x, y);}, gtwrap::internal::py_arg<const string&>("x"), gtwrap::internal::py_arg<size_t>("y"));
m_.def("MultiTemplatedFunctionDoubleSize_tDouble",[](const double& x, size_t y){return ::MultiTemplatedFunction<double,size_t,double>(x, y);}, gtwrap::internal::py_arg<const double&>("x"), gtwrap::internal::py_arg<size_t>("y"));
m_.def("DefaultFuncInt",[](int a, int b){ ::DefaultFuncInt(a, b);}, gtwrap::internal::py_arg<int>("a") = 123, gtwrap::internal::py_arg<int>("b") = 0);
m_.def("DefaultFuncString",[](const string& s, const string& name){ ::DefaultFuncString(s, name);}, gtwrap::internal::py_arg<const string&>("s") = "hello", gtwrap::internal::py_arg<const string&>("name") = "");
m_.def("DefaultFuncObj",[](const gtsam::KeyFormatter& keyFormatter){ ::DefaultFuncObj(keyFormatter);}, gtwrap::internal::py_arg<const gtsam::KeyFormatter&>("keyFormatter") = gtsam::DefaultKeyFormatter);
m_.def("DefaultFuncZero",[](int a, int b, double c, int d, bool e){ ::DefaultFuncZero(a, b, c, d, e);}, gtwrap::internal::py_arg<int>("a"), gtwrap::internal::py_arg<int>("b"), gtwrap::internal::py_arg<double>("c") = 0.0, gtwrap::internal::py_arg<int>("d") = 0, gtwrap::internal::py_arg<bool>("e") = false);
m_.def("DefaultFuncVector",[](const std::vector<int>& i, const std::vector<string>& s){ ::DefaultFuncVector(i, s);}, gtwrap::internal::py_arg<const std::vector<int>&>("i") = {1, 2, 3}, gtwrap::internal::py_arg<const std::vector<string>&>("s") = {"borglab", "gtsam"});
m_.def("setPose",[](const gtsam::Pose3& pose){ ::setPose(pose);}, gtwrap::internal::py_arg<const gtsam::Pose3&>("pose") = gtsam::Pose3());
m_.def("EliminateDiscrete",[](const gtsam::DiscreteFactorGraph& factors, const gtsam::Ordering& frontalKeys){return ::EliminateDiscrete(factors, frontalKeys);}, gtwrap::internal::py_arg<const gtsam::DiscreteFactorGraph&>("factors"), gtwrap::internal::py_arg<const gtsam::Ordering&>("frontalKeys"));
m_.def("triangulatePoint3Cal3_S2",[](const gtsam::Pose3Vector& poses, std::shared_ptr<gtsam::Cal3_S2> sharedCal, const gtsam::Point2Vector& measurements, double rank_tol, bool optimize, const gtsam::SharedNoiseModel& model){return ::triangulatePoint3<gtsam::Cal3_S2>(poses, sharedCal, measurements, rank_tol, optimize, model);}, gtwrap::internal::py_arg<const gtsam::Pose3Vector&>("poses"), gtwrap::internal::py_arg<std::shared_ptr<gtsam::Cal3_S2>>("sharedCal"), gtwrap::internal::py_arg<const gtsam::Point2Vector&>("measurements"), gtwrap::internal::py_arg<double>("rank_tol"), gtwrap::internal::py_arg<bool>("optimize"), gtwrap::internal::py_arg<const gtsam::SharedNoiseModel&>("model") = nullptr);
m_.def("FindKarcherMeanPoint3",[](const std::vector<gtsam::Point3>& elements){return ::FindKarcherMean<gtsam::Point3>(elements);}, gtwrap::internal::py_arg<const std::vector<gtsam::Point3>&>("elements"));
m_.def("FindKarcherMeanSO3",[](const std::vector<gtsam::SO3>& elements){return ::FindKarcherMean<gtsam::SO3>(elements);}, gtwrap::internal::py_arg<const std::vector<gtsam::SO3>&>("elements"));
m_.def("FindKarcherMeanSO4",[](const std::vector<gtsam::SO4>& elements){return ::FindKarcherMean<gtsam::SO4>(elements);}, gtwrap::internal::py_arg<const std::vector<gtsam::SO4>&>("elements"));
m_.def("FindKarcherMeanPose3",[](const std::vector<gtsam::Pose3>& elements){return ::FindKarcherMean<gtsam::Pose3>(elements);}, gtwrap::internal::py_arg<const std::vector<gtsam::Pose3>&>("elements"));
m_.def("TemplatedFunctionRot3",[](const gtsam::Rot3& t){ ::TemplatedFunction<gtsam::Rot3>(t);}, gtwrap::internal::py_arg<const gtsam::Rot3&>("t"));

#include "python/specializations.h"

Expand Down
42 changes: 30 additions & 12 deletions tests/expected/python/geometry_pybind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@
#include "gtsam/geometry/Point2.h"
#include "gtsam/geometry/Point3.h"
#include <boost/serialization/export.hpp>
#include <type_traits>

namespace gtwrap {
namespace internal {

template <typename T>
struct PyArgPolicy {
static pybind11::arg make(const char* name) { return pybind11::arg(name); }
};

template <typename T>
pybind11::arg py_arg(const char* name) {
return PyArgPolicy<typename std::decay<T>::type>::make(name);
}

} // namespace internal
} // namespace gtwrap


BOOST_CLASS_EXPORT(gtsam::Point2)
BOOST_CLASS_EXPORT(gtsam::Point3)
Expand All @@ -23,20 +41,20 @@ PYBIND11_MODULE(geometry_py, m_) {

py::class_<gtsam::Point2, std::shared_ptr<gtsam::Point2>>(m_gtsam, "Point2")
.def(py::init<>())
.def(py::init<double, double>(), py::arg("x"), py::arg("y"))
.def(py::init<double, double>(), gtwrap::internal::py_arg<double>("x"), gtwrap::internal::py_arg<double>("y"))
.def("x",[](gtsam::Point2* self){return self->x();})
.def("y",[](gtsam::Point2* self){return self->y();})
.def("dim",[](gtsam::Point2* self){return self->dim();})
.def("returnChar",[](gtsam::Point2* self){return self->returnChar();})
.def("argChar",[](gtsam::Point2* self, char a){ self->argChar(a);}, py::arg("a"))
.def("argChar",[](gtsam::Point2* self, std::shared_ptr<char> a){ self->argChar(a);}, py::arg("a"))
.def("argChar",[](gtsam::Point2* self, char& a){ self->argChar(a);}, py::arg("a"))
.def("argChar",[](gtsam::Point2* self, char* a){ self->argChar(a);}, py::arg("a"))
.def("argChar",[](gtsam::Point2* self, const std::shared_ptr<char> a){ self->argChar(a);}, py::arg("a"))
.def("argChar",[](gtsam::Point2* self, const char& a){ self->argChar(a);}, py::arg("a"))
.def("argChar",[](gtsam::Point2* self, const char* a){ self->argChar(a);}, py::arg("a"))
.def("argUChar",[](gtsam::Point2* self, unsigned char a){ self->argUChar(a);}, py::arg("a"))
.def("eigenArguments",[](gtsam::Point2* self, const gtsam::Vector& v, const gtsam::Matrix& m){ self->eigenArguments(v, m);}, py::arg("v"), py::arg("m"))
.def("argChar",[](gtsam::Point2* self, char a){ self->argChar(a);}, gtwrap::internal::py_arg<char>("a"))
.def("argChar",[](gtsam::Point2* self, std::shared_ptr<char> a){ self->argChar(a);}, gtwrap::internal::py_arg<std::shared_ptr<char>>("a"))
.def("argChar",[](gtsam::Point2* self, char& a){ self->argChar(a);}, gtwrap::internal::py_arg<char&>("a"))
.def("argChar",[](gtsam::Point2* self, char* a){ self->argChar(a);}, gtwrap::internal::py_arg<char*>("a"))
.def("argChar",[](gtsam::Point2* self, const std::shared_ptr<char> a){ self->argChar(a);}, gtwrap::internal::py_arg<const std::shared_ptr<char>>("a"))
.def("argChar",[](gtsam::Point2* self, const char& a){ self->argChar(a);}, gtwrap::internal::py_arg<const char&>("a"))
.def("argChar",[](gtsam::Point2* self, const char* a){ self->argChar(a);}, gtwrap::internal::py_arg<const char*>("a"))
.def("argUChar",[](gtsam::Point2* self, unsigned char a){ self->argUChar(a);}, gtwrap::internal::py_arg<unsigned char>("a"))
.def("eigenArguments",[](gtsam::Point2* self, const gtsam::Vector& v, const gtsam::Matrix& m){ self->eigenArguments(v, m);}, gtwrap::internal::py_arg<const gtsam::Vector&>("v"), gtwrap::internal::py_arg<const gtsam::Matrix&>("m"))
.def("vectorConfusion",[](gtsam::Point2* self){return self->vectorConfusion();})
.def("serialize", [](gtsam::Point2* self){ return gtsam::serialize(*self); })
.def("deserialize", [](gtsam::Point2* self, string serialized){ gtsam::deserialize(serialized, *self); }, py::arg("serialized"))
Expand All @@ -45,15 +63,15 @@ PYBIND11_MODULE(geometry_py, m_) {
[](py::tuple t){ /* __setstate__ */ gtsam::Point2 obj; gtsam::deserialize(t[0].cast<std::string>(), obj); return obj; }));

py::class_<gtsam::Point3, std::shared_ptr<gtsam::Point3>>(m_gtsam, "Point3")
.def(py::init<double, double, double>(), py::arg("x"), py::arg("y"), py::arg("z"))
.def(py::init<double, double, double>(), gtwrap::internal::py_arg<double>("x"), gtwrap::internal::py_arg<double>("y"), gtwrap::internal::py_arg<double>("z"))
.def("norm",[](gtsam::Point3* self){return self->norm();})
.def("serialize", [](gtsam::Point3* self){ return gtsam::serialize(*self); })
.def("deserialize", [](gtsam::Point3* self, string serialized){ gtsam::deserialize(serialized, *self); }, py::arg("serialized"))
.def(py::pickle(
[](const gtsam::Point3 &a){ /* __getstate__: Returns a string that encodes the state of the object */ return py::make_tuple(gtsam::serialize(a)); },
[](py::tuple t){ /* __setstate__ */ gtsam::Point3 obj; gtsam::deserialize(t[0].cast<std::string>(), obj); return obj; }))
.def_static("staticFunction",[](){return gtsam::Point3::staticFunction();})
.def_static("StaticFunctionRet",[](double z){return gtsam::Point3::StaticFunctionRet(z);}, py::arg("z"));
.def_static("StaticFunctionRet",[](double z){return gtsam::Point3::StaticFunctionRet(z);}, gtwrap::internal::py_arg<double>("z"));


#include "python/specializations.h"
Expand Down
Loading
Loading