From c78ca4bd02e94c87a233e307533afb34241a6138 Mon Sep 17 00:00:00 2001 From: Varun Agrawal Date: Fri, 26 Mar 2021 00:54:01 -0400 Subject: [PATCH] Squashed 'wrap/' changes from 9a467794e..96ccdfd0b 96ccdfd0b Merge pull request #65 from borglab/fix/special-cases 04c06b7e6 Merge pull request #63 from borglab/fix/cmake bf2c91bd2 fix issue in template instantiation generator 152dbcb12 test for special cases d03004b24 fixed the cmake to discover the correct python version and set all corresponding variables 4cf66e0da Merge pull request #61 from borglab/fix/python-variables 80558e35b added more status messages and set the PYBIND11_PYTHON_VERSION each time 73afd1b0a set both sets of Python variables and find python version when including PybindWrap REVERT: 9a467794e Merge pull request #61 from borglab/fix/python-variables REVERT: 6bae7af99 added more status messages and set the PYBIND11_PYTHON_VERSION each time REVERT: 5129cf3b9 set both sets of Python variables and find python version when including PybindWrap git-subtree-dir: wrap git-subtree-split: 96ccdfd0b84a4dbf1b3e9ed31b95ebc2758be9cc --- cmake/GtwrapUtils.cmake | 35 +- cmake/PybindWrap.cmake | 4 +- gtwrap/template_instantiator.py | 10 +- .../matlab/+gtsam/NonlinearFactorGraph.m | 44 +++ .../matlab/+gtsam/PinholeCameraCal3Bundler.m | 31 ++ .../expected/matlab/special_cases_wrapper.cpp | 340 ++++++++++++++++++ .../expected/python/special_cases_pybind.cpp | 35 ++ tests/fixtures/special_cases.i | 17 + tests/test_matlab_wrapper.py | 38 +- tests/test_pybind_wrapper.py | 12 + 10 files changed, 542 insertions(+), 24 deletions(-) create mode 100644 tests/expected/matlab/+gtsam/NonlinearFactorGraph.m create mode 100644 tests/expected/matlab/+gtsam/PinholeCameraCal3Bundler.m create mode 100644 tests/expected/matlab/special_cases_wrapper.cpp create mode 100644 tests/expected/python/special_cases_pybind.cpp create mode 100644 tests/fixtures/special_cases.i diff --git a/cmake/GtwrapUtils.cmake b/cmake/GtwrapUtils.cmake index 01cdd32b98..a3a77708c5 100644 --- a/cmake/GtwrapUtils.cmake +++ b/cmake/GtwrapUtils.cmake @@ -1,5 +1,6 @@ # Utilities to help with wrapping. +# Use CMake's find_package to find the version of Python installed. macro(get_python_version) if(${CMAKE_VERSION} VERSION_LESS "3.12.0") # Use older version of cmake's find_python @@ -13,6 +14,23 @@ macro(get_python_version) find_package(PythonLibs ${PYTHON_VERSION_STRING}) + else() + # Get info about the Python interpreter + # https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython + find_package(Python COMPONENTS Interpreter Development) + + if(NOT ${Python_FOUND}) + message( + FATAL_ERROR + "Cannot find Python interpreter. Please install Python>=3.5.") + endif() + + endif() +endmacro() + +# Depending on the version of CMake, ensure all the appropriate variables are set. +macro(configure_python_variables) + if(${CMAKE_VERSION} VERSION_LESS "3.12.0") set(Python_VERSION_MAJOR ${PYTHON_VERSION_MAJOR} CACHE INTERNAL "") @@ -24,19 +42,9 @@ macro(get_python_version) CACHE INTERNAL "") set(Python_EXECUTABLE ${PYTHON_EXECUTABLE} - CACHE INTERNAL "") + CACHE PATH "") else() - # Get info about the Python interpreter - # https://cmake.org/cmake/help/latest/module/FindPython.html#module:FindPython - find_package(Python COMPONENTS Interpreter Development) - - if(NOT ${Python_FOUND}) - message( - FATAL_ERROR - "Cannot find Python interpreter. Please install Python>=3.5.") - endif() - # Set both sets of variables set(PYTHON_VERSION_MAJOR ${Python_VERSION_MAJOR} @@ -49,7 +57,7 @@ macro(get_python_version) CACHE INTERNAL "") set(PYTHON_EXECUTABLE ${Python_EXECUTABLE} - CACHE INTERNAL "") + CACHE PATH "") endif() endmacro() @@ -85,4 +93,7 @@ macro(gtwrap_get_python_version WRAP_PYTHON_VERSION) EXACT) endif() + # (Always) Configure the variables once we find the python package + configure_python_variables() + endmacro() diff --git a/cmake/PybindWrap.cmake b/cmake/PybindWrap.cmake index 2c07e2b509..dc581be495 100644 --- a/cmake/PybindWrap.cmake +++ b/cmake/PybindWrap.cmake @@ -7,10 +7,10 @@ endif() # Get the Python version include(GtwrapUtils) -message(status "Checking Python Version") +message(STATUS "Checking Python Version") gtwrap_get_python_version(${WRAP_PYTHON_VERSION}) -message(status "Setting Python version for wrapper") +message(STATUS "Setting Python version for wrapper") set(PYBIND11_PYTHON_VERSION ${WRAP_PYTHON_VERSION}) # User-friendly Pybind11 wrapping and installing function. diff --git a/gtwrap/template_instantiator.py b/gtwrap/template_instantiator.py index 7ae79e2176..5651a2a6f2 100644 --- a/gtwrap/template_instantiator.py +++ b/gtwrap/template_instantiator.py @@ -206,7 +206,7 @@ class InstantiatedMethod(parser.Method): """ We can only instantiate template methods with a single template parameter. """ - def __init__(self, original, instantiations=''): + def __init__(self, original, instantiations: List[parser.Typename]=''): self.original = original self.instantiations = instantiations self.template = '' @@ -246,11 +246,9 @@ def __init__(self, original, instantiations=''): def to_cpp(self): """Generate the C++ code for wrapping.""" if self.original.template: - instantiation_list = [ - # Get the fully qualified name - "::".join(x.namespaces + [x.name]) - for x in self.instantiations - ] + # to_cpp will handle all the namespacing and templating + instantiation_list = [x.to_cpp() for x in self.instantiations] + # now can simply combine the instantiations, separated by commas ret = "{}<{}>".format(self.original.name, ",".join(instantiation_list)) else: diff --git a/tests/expected/matlab/+gtsam/NonlinearFactorGraph.m b/tests/expected/matlab/+gtsam/NonlinearFactorGraph.m new file mode 100644 index 0000000000..4b4704e87e --- /dev/null +++ b/tests/expected/matlab/+gtsam/NonlinearFactorGraph.m @@ -0,0 +1,44 @@ +%class NonlinearFactorGraph, see Doxygen page for details +%at https://gtsam.org/doxygen/ +% +%-------Methods------- +%addPriorPinholeCameraCal3Bundler(size_t key, PinholeCamera prior, Base noiseModel) : returns void +% +classdef NonlinearFactorGraph < handle + properties + ptr_gtsamNonlinearFactorGraph = 0 + end + methods + function obj = NonlinearFactorGraph(varargin) + if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682) + my_ptr = varargin{2}; + special_cases_wrapper(0, my_ptr); + else + error('Arguments do not match any overload of gtsam.NonlinearFactorGraph constructor'); + end + obj.ptr_gtsamNonlinearFactorGraph = my_ptr; + end + + function delete(obj) + special_cases_wrapper(1, obj.ptr_gtsamNonlinearFactorGraph); + end + + function display(obj), obj.print(''); end + %DISPLAY Calls print on the object + function disp(obj), obj.display; end + %DISP Calls print on the object + function varargout = addPriorPinholeCameraCal3Bundler(this, varargin) + % ADDPRIORPINHOLECAMERACAL3BUNDLER usage: addPriorPinholeCameraCal3Bundler(size_t key, PinholeCamera prior, Base noiseModel) : returns void + % Doxygen can be found at https://gtsam.org/doxygen/ + if length(varargin) == 3 && isa(varargin{1},'numeric') && isa(varargin{2},'gtsam.PinholeCameraCal3Bundler') && isa(varargin{3},'gtsam.noiseModel.Base') + special_cases_wrapper(2, this, varargin{:}); + return + end + error('Arguments do not match any overload of function gtsam.NonlinearFactorGraph.addPriorPinholeCameraCal3Bundler'); + end + + end + + methods(Static = true) + end +end diff --git a/tests/expected/matlab/+gtsam/PinholeCameraCal3Bundler.m b/tests/expected/matlab/+gtsam/PinholeCameraCal3Bundler.m new file mode 100644 index 0000000000..3e8451e961 --- /dev/null +++ b/tests/expected/matlab/+gtsam/PinholeCameraCal3Bundler.m @@ -0,0 +1,31 @@ +%class PinholeCameraCal3Bundler, see Doxygen page for details +%at https://gtsam.org/doxygen/ +% +classdef PinholeCameraCal3Bundler < handle + properties + ptr_gtsamPinholeCameraCal3Bundler = 0 + end + methods + function obj = PinholeCameraCal3Bundler(varargin) + if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682) + my_ptr = varargin{2}; + special_cases_wrapper(3, my_ptr); + else + error('Arguments do not match any overload of gtsam.PinholeCameraCal3Bundler constructor'); + end + obj.ptr_gtsamPinholeCameraCal3Bundler = my_ptr; + end + + function delete(obj) + special_cases_wrapper(4, obj.ptr_gtsamPinholeCameraCal3Bundler); + end + + function display(obj), obj.print(''); end + %DISPLAY Calls print on the object + function disp(obj), obj.display; end + %DISP Calls print on the object + end + + methods(Static = true) + end +end diff --git a/tests/expected/matlab/special_cases_wrapper.cpp b/tests/expected/matlab/special_cases_wrapper.cpp new file mode 100644 index 0000000000..f1c03e9a17 --- /dev/null +++ b/tests/expected/matlab/special_cases_wrapper.cpp @@ -0,0 +1,340 @@ +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef Fun FunDouble; +typedef PrimitiveRef PrimitiveRefDouble; +typedef MyVector<3> MyVector3; +typedef MyVector<12> MyVector12; +typedef MultipleTemplates MultipleTemplatesIntDouble; +typedef MultipleTemplates MultipleTemplatesIntFloat; +typedef MyFactor MyFactorPosePoint2; +typedef MyTemplate MyTemplatePoint2; +typedef MyTemplate MyTemplateMatrix; +typedef gtsam::PinholeCamera PinholeCameraCal3Bundler; + +BOOST_CLASS_EXPORT_GUID(gtsam::Point2, "gtsamPoint2"); +BOOST_CLASS_EXPORT_GUID(gtsam::Point3, "gtsamPoint3"); + +typedef std::set*> Collector_FunRange; +static Collector_FunRange collector_FunRange; +typedef std::set*> Collector_FunDouble; +static Collector_FunDouble collector_FunDouble; +typedef std::set*> Collector_Test; +static Collector_Test collector_Test; +typedef std::set*> Collector_PrimitiveRefDouble; +static Collector_PrimitiveRefDouble collector_PrimitiveRefDouble; +typedef std::set*> Collector_MyVector3; +static Collector_MyVector3 collector_MyVector3; +typedef std::set*> Collector_MyVector12; +static Collector_MyVector12 collector_MyVector12; +typedef std::set*> Collector_MultipleTemplatesIntDouble; +static Collector_MultipleTemplatesIntDouble collector_MultipleTemplatesIntDouble; +typedef std::set*> Collector_MultipleTemplatesIntFloat; +static Collector_MultipleTemplatesIntFloat collector_MultipleTemplatesIntFloat; +typedef std::set*> Collector_MyFactorPosePoint2; +static Collector_MyFactorPosePoint2 collector_MyFactorPosePoint2; +typedef std::set*> Collector_gtsamPoint2; +static Collector_gtsamPoint2 collector_gtsamPoint2; +typedef std::set*> Collector_gtsamPoint3; +static Collector_gtsamPoint3 collector_gtsamPoint3; +typedef std::set*> Collector_MyBase; +static Collector_MyBase collector_MyBase; +typedef std::set*> Collector_MyTemplatePoint2; +static Collector_MyTemplatePoint2 collector_MyTemplatePoint2; +typedef std::set*> Collector_MyTemplateMatrix; +static Collector_MyTemplateMatrix collector_MyTemplateMatrix; +typedef std::set*> Collector_ns1ClassA; +static Collector_ns1ClassA collector_ns1ClassA; +typedef std::set*> Collector_ns1ClassB; +static Collector_ns1ClassB collector_ns1ClassB; +typedef std::set*> Collector_ns2ClassA; +static Collector_ns2ClassA collector_ns2ClassA; +typedef std::set*> Collector_ns2ns3ClassB; +static Collector_ns2ns3ClassB collector_ns2ns3ClassB; +typedef std::set*> Collector_ns2ClassC; +static Collector_ns2ClassC collector_ns2ClassC; +typedef std::set*> Collector_ClassD; +static Collector_ClassD collector_ClassD; +typedef std::set*> Collector_gtsamNonlinearFactorGraph; +static Collector_gtsamNonlinearFactorGraph collector_gtsamNonlinearFactorGraph; +typedef std::set*> Collector_gtsamPinholeCameraCal3Bundler; +static Collector_gtsamPinholeCameraCal3Bundler collector_gtsamPinholeCameraCal3Bundler; + +void _deleteAllObjects() +{ + mstream mout; + std::streambuf *outbuf = std::cout.rdbuf(&mout); + + bool anyDeleted = false; + { for(Collector_FunRange::iterator iter = collector_FunRange.begin(); + iter != collector_FunRange.end(); ) { + delete *iter; + collector_FunRange.erase(iter++); + anyDeleted = true; + } } + { for(Collector_FunDouble::iterator iter = collector_FunDouble.begin(); + iter != collector_FunDouble.end(); ) { + delete *iter; + collector_FunDouble.erase(iter++); + anyDeleted = true; + } } + { for(Collector_Test::iterator iter = collector_Test.begin(); + iter != collector_Test.end(); ) { + delete *iter; + collector_Test.erase(iter++); + anyDeleted = true; + } } + { for(Collector_PrimitiveRefDouble::iterator iter = collector_PrimitiveRefDouble.begin(); + iter != collector_PrimitiveRefDouble.end(); ) { + delete *iter; + collector_PrimitiveRefDouble.erase(iter++); + anyDeleted = true; + } } + { for(Collector_MyVector3::iterator iter = collector_MyVector3.begin(); + iter != collector_MyVector3.end(); ) { + delete *iter; + collector_MyVector3.erase(iter++); + anyDeleted = true; + } } + { for(Collector_MyVector12::iterator iter = collector_MyVector12.begin(); + iter != collector_MyVector12.end(); ) { + delete *iter; + collector_MyVector12.erase(iter++); + anyDeleted = true; + } } + { for(Collector_MultipleTemplatesIntDouble::iterator iter = collector_MultipleTemplatesIntDouble.begin(); + iter != collector_MultipleTemplatesIntDouble.end(); ) { + delete *iter; + collector_MultipleTemplatesIntDouble.erase(iter++); + anyDeleted = true; + } } + { for(Collector_MultipleTemplatesIntFloat::iterator iter = collector_MultipleTemplatesIntFloat.begin(); + iter != collector_MultipleTemplatesIntFloat.end(); ) { + delete *iter; + collector_MultipleTemplatesIntFloat.erase(iter++); + anyDeleted = true; + } } + { for(Collector_MyFactorPosePoint2::iterator iter = collector_MyFactorPosePoint2.begin(); + iter != collector_MyFactorPosePoint2.end(); ) { + delete *iter; + collector_MyFactorPosePoint2.erase(iter++); + anyDeleted = true; + } } + { for(Collector_gtsamPoint2::iterator iter = collector_gtsamPoint2.begin(); + iter != collector_gtsamPoint2.end(); ) { + delete *iter; + collector_gtsamPoint2.erase(iter++); + anyDeleted = true; + } } + { for(Collector_gtsamPoint3::iterator iter = collector_gtsamPoint3.begin(); + iter != collector_gtsamPoint3.end(); ) { + delete *iter; + collector_gtsamPoint3.erase(iter++); + anyDeleted = true; + } } + { for(Collector_MyBase::iterator iter = collector_MyBase.begin(); + iter != collector_MyBase.end(); ) { + delete *iter; + collector_MyBase.erase(iter++); + anyDeleted = true; + } } + { for(Collector_MyTemplatePoint2::iterator iter = collector_MyTemplatePoint2.begin(); + iter != collector_MyTemplatePoint2.end(); ) { + delete *iter; + collector_MyTemplatePoint2.erase(iter++); + anyDeleted = true; + } } + { for(Collector_MyTemplateMatrix::iterator iter = collector_MyTemplateMatrix.begin(); + iter != collector_MyTemplateMatrix.end(); ) { + delete *iter; + collector_MyTemplateMatrix.erase(iter++); + anyDeleted = true; + } } + { for(Collector_ns1ClassA::iterator iter = collector_ns1ClassA.begin(); + iter != collector_ns1ClassA.end(); ) { + delete *iter; + collector_ns1ClassA.erase(iter++); + anyDeleted = true; + } } + { for(Collector_ns1ClassB::iterator iter = collector_ns1ClassB.begin(); + iter != collector_ns1ClassB.end(); ) { + delete *iter; + collector_ns1ClassB.erase(iter++); + anyDeleted = true; + } } + { for(Collector_ns2ClassA::iterator iter = collector_ns2ClassA.begin(); + iter != collector_ns2ClassA.end(); ) { + delete *iter; + collector_ns2ClassA.erase(iter++); + anyDeleted = true; + } } + { for(Collector_ns2ns3ClassB::iterator iter = collector_ns2ns3ClassB.begin(); + iter != collector_ns2ns3ClassB.end(); ) { + delete *iter; + collector_ns2ns3ClassB.erase(iter++); + anyDeleted = true; + } } + { for(Collector_ns2ClassC::iterator iter = collector_ns2ClassC.begin(); + iter != collector_ns2ClassC.end(); ) { + delete *iter; + collector_ns2ClassC.erase(iter++); + anyDeleted = true; + } } + { for(Collector_ClassD::iterator iter = collector_ClassD.begin(); + iter != collector_ClassD.end(); ) { + delete *iter; + collector_ClassD.erase(iter++); + anyDeleted = true; + } } + { for(Collector_gtsamNonlinearFactorGraph::iterator iter = collector_gtsamNonlinearFactorGraph.begin(); + iter != collector_gtsamNonlinearFactorGraph.end(); ) { + delete *iter; + collector_gtsamNonlinearFactorGraph.erase(iter++); + anyDeleted = true; + } } + { for(Collector_gtsamPinholeCameraCal3Bundler::iterator iter = collector_gtsamPinholeCameraCal3Bundler.begin(); + iter != collector_gtsamPinholeCameraCal3Bundler.end(); ) { + delete *iter; + collector_gtsamPinholeCameraCal3Bundler.erase(iter++); + anyDeleted = true; + } } + if(anyDeleted) + cout << + "WARNING: Wrap modules with variables in the workspace have been reloaded due to\n" + "calling destructors, call 'clear all' again if you plan to now recompile a wrap\n" + "module, so that your recompiled module is used instead of the old one." << endl; + std::cout.rdbuf(outbuf); +} + +void _special_cases_RTTIRegister() { + const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_special_cases_rttiRegistry_created"); + if(!alreadyCreated) { + std::map types; + types.insert(std::make_pair(typeid(MyBase).name(), "MyBase")); + types.insert(std::make_pair(typeid(MyTemplatePoint2).name(), "MyTemplatePoint2")); + types.insert(std::make_pair(typeid(MyTemplateMatrix).name(), "MyTemplateMatrix")); + + mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry"); + if(!registry) + registry = mxCreateStructMatrix(1, 1, 0, NULL); + typedef std::pair StringPair; + for(const StringPair& rtti_matlab: types) { + int fieldId = mxAddField(registry, rtti_matlab.first.c_str()); + if(fieldId < 0) + mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); + mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str()); + mxSetFieldByNumber(registry, 0, fieldId, matlabName); + } + if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) + mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); + mxDestroyArray(registry); + + mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL); + if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) + mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); + mxDestroyArray(newAlreadyCreated); + } +} + +void gtsamNonlinearFactorGraph_collectorInsertAndMakeBase_0(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + mexAtExit(&_deleteAllObjects); + typedef boost::shared_ptr Shared; + + Shared *self = *reinterpret_cast (mxGetData(in[0])); + collector_gtsamNonlinearFactorGraph.insert(self); +} + +void gtsamNonlinearFactorGraph_deconstructor_1(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + typedef boost::shared_ptr Shared; + checkArguments("delete_gtsamNonlinearFactorGraph",nargout,nargin,1); + Shared *self = *reinterpret_cast(mxGetData(in[0])); + Collector_gtsamNonlinearFactorGraph::iterator item; + item = collector_gtsamNonlinearFactorGraph.find(self); + if(item != collector_gtsamNonlinearFactorGraph.end()) { + delete self; + collector_gtsamNonlinearFactorGraph.erase(item); + } +} + +void gtsamNonlinearFactorGraph_addPrior_2(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + checkArguments("addPriorPinholeCameraCal3Bundler",nargout,nargin-1,3); + auto obj = unwrap_shared_ptr(in[0], "ptr_gtsamNonlinearFactorGraph"); + size_t key = unwrap< size_t >(in[1]); + gtsam::PinholeCamera& prior = *unwrap_shared_ptr< gtsam::PinholeCamera >(in[2], "ptr_gtsamPinholeCameraCal3Bundler"); + boost::shared_ptr noiseModel = unwrap_shared_ptr< gtsam::noiseModel::Base >(in[3], "ptr_gtsamnoiseModelBase"); + obj->addPrior>(key,prior,noiseModel); +} + +void gtsamPinholeCameraCal3Bundler_collectorInsertAndMakeBase_3(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + mexAtExit(&_deleteAllObjects); + typedef boost::shared_ptr> Shared; + + Shared *self = *reinterpret_cast (mxGetData(in[0])); + collector_gtsamPinholeCameraCal3Bundler.insert(self); +} + +void gtsamPinholeCameraCal3Bundler_deconstructor_4(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + typedef boost::shared_ptr> Shared; + checkArguments("delete_gtsamPinholeCameraCal3Bundler",nargout,nargin,1); + Shared *self = *reinterpret_cast(mxGetData(in[0])); + Collector_gtsamPinholeCameraCal3Bundler::iterator item; + item = collector_gtsamPinholeCameraCal3Bundler.find(self); + if(item != collector_gtsamPinholeCameraCal3Bundler.end()) { + delete self; + collector_gtsamPinholeCameraCal3Bundler.erase(item); + } +} + + +void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + mstream mout; + std::streambuf *outbuf = std::cout.rdbuf(&mout); + + _special_cases_RTTIRegister(); + + int id = unwrap(in[0]); + + try { + switch(id) { + case 0: + gtsamNonlinearFactorGraph_collectorInsertAndMakeBase_0(nargout, out, nargin-1, in+1); + break; + case 1: + gtsamNonlinearFactorGraph_deconstructor_1(nargout, out, nargin-1, in+1); + break; + case 2: + gtsamNonlinearFactorGraph_addPrior_2(nargout, out, nargin-1, in+1); + break; + case 3: + gtsamPinholeCameraCal3Bundler_collectorInsertAndMakeBase_3(nargout, out, nargin-1, in+1); + break; + case 4: + gtsamPinholeCameraCal3Bundler_deconstructor_4(nargout, out, nargin-1, in+1); + break; + } + } catch(const std::exception& e) { + mexErrMsgTxt(("Exception from gtsam:\n" + std::string(e.what()) + "\n").c_str()); + } + + std::cout.rdbuf(outbuf); +} diff --git a/tests/expected/python/special_cases_pybind.cpp b/tests/expected/python/special_cases_pybind.cpp new file mode 100644 index 0000000000..fb15a004d2 --- /dev/null +++ b/tests/expected/python/special_cases_pybind.cpp @@ -0,0 +1,35 @@ + + +#include +#include +#include +#include "gtsam/nonlinear/utilities.h" // for RedirectCout. + +#include "gtsam/geometry/Cal3Bundler.h" + +#include "wrap/serialization.h" +#include + + + + + +using namespace std; + +namespace py = pybind11; + +PYBIND11_MODULE(special_cases_py, m_) { + m_.doc() = "pybind11 wrapper of special_cases_py"; + + pybind11::module m_gtsam = m_.def_submodule("gtsam", "gtsam submodule"); + + py::class_>(m_gtsam, "NonlinearFactorGraph") + .def("addPriorPinholeCameraCal3Bundler",[](gtsam::NonlinearFactorGraph* self, size_t key, const gtsam::PinholeCamera& prior, const std::shared_ptr& noiseModel){ self->addPrior>(key, prior, noiseModel);}, py::arg("key"), py::arg("prior"), py::arg("noiseModel")); + + py::class_, std::shared_ptr>>(m_gtsam, "PinholeCameraCal3Bundler"); + + +#include "python/specializations.h" + +} + diff --git a/tests/fixtures/special_cases.i b/tests/fixtures/special_cases.i new file mode 100644 index 0000000000..9451eed241 --- /dev/null +++ b/tests/fixtures/special_cases.i @@ -0,0 +1,17 @@ +// Check for templated class as template argument for method! +namespace gtsam { + +#include + +class Cal3Bundler; + +template +class PinholeCamera {}; +typedef gtsam::PinholeCamera PinholeCameraCal3Bundler; + +class NonlinearFactorGraph { + template}> + void addPrior(size_t key, const T& prior, const gtsam::noiseModel::Base* noiseModel); +}; + +} \ No newline at end of file diff --git a/tests/test_matlab_wrapper.py b/tests/test_matlab_wrapper.py index 83398f72a1..02d40cb457 100644 --- a/tests/test_matlab_wrapper.py +++ b/tests/test_matlab_wrapper.py @@ -36,7 +36,7 @@ class TestWrap(unittest.TestCase): logger.remove() # remove the default sink logger.add(sys.stderr, format="{time} {level} {message}", level="INFO") - def generate_content(self, cc_content, path=''): + def generate_content(self, cc_content, path=MATLAB_ACTUAL_DIR): """Generate files and folders from matlab wrapper content. Keyword arguments: @@ -45,9 +45,6 @@ def generate_content(self, cc_content, path=''): (folder_name, [(file_name, file_content)]) path -- the path to the files parent folder within the main folder """ - if path == '': - path = self.MATLAB_ACTUAL_DIR - for c in cc_content: if isinstance(c, list): if len(c) == 0: @@ -275,6 +272,39 @@ def test_namspaces(self): for file in files: self.compare_and_diff(file) + def test_special_cases(self): + """ + Tests for some unique, non-trivial features. + """ + with open(osp.join(self.INTERFACE_DIR, 'special_cases.i'), 'r') as f: + content = f.read() + + if not osp.exists(self.MATLAB_ACTUAL_DIR): + os.mkdir(self.MATLAB_ACTUAL_DIR) + + module = parser.Module.parseString(content) + + instantiator.instantiate_namespace_inplace(module) + + wrapper = MatlabWrapper( + module=module, + module_name='special_cases', + top_module_namespace=['gtsam'], + ignore_classes=[''], + ) + + cc_content = wrapper.wrap() + + self.generate_content(cc_content) + + files = [ + 'special_cases_wrapper.cpp', + '+gtsam/PinholeCameraCal3Bundler.m', + '+gtsam/NonlinearFactorGraph.m', + ] + + for file in files: + self.compare_and_diff(file) if __name__ == '__main__': unittest.main() diff --git a/tests/test_pybind_wrapper.py b/tests/test_pybind_wrapper.py index 5f6b821411..c5df5deb58 100644 --- a/tests/test_pybind_wrapper.py +++ b/tests/test_pybind_wrapper.py @@ -134,6 +134,18 @@ def test_namespaces(self): self.compare_and_diff('namespaces_pybind.cpp', output) + def test_special_cases(self): + """ + Tests for some unique, non-trivial features. + """ + with open(osp.join(self.INTERFACE_DIR, 'special_cases.i'), 'r') as f: + content = f.read() + + output = self.wrap_content(content, 'special_cases_py', + self.PYTHON_ACTUAL_DIR) + + self.compare_and_diff('special_cases_pybind.cpp', output) + if __name__ == '__main__': unittest.main()