diff --git a/.gitignore b/.gitignore index ed9bd8621..8e2bafa7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ __pycache__/ .vscode/ *build* +*install* *dist* *.egg-info diff --git a/CMakeLists.txt b/CMakeLists.txt index 883f438e6..91fbaec64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,54 +1,83 @@ cmake_minimum_required(VERSION 3.9) # Set the project name and version -project(GTwrap VERSION 1.0) +project(gtwrap VERSION 1.0) # ############################################################################## # General configuration -set(WRAP_PYTHON_VERSION - "Default" - CACHE STRING "The Python version to use for wrapping") - include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/GtwrapUtils.cmake) gtwrap_get_python_version(${WRAP_PYTHON_VERSION}) -# ############################################################################## -# Install the CMake file to be used by other projects +# Set the variables to be used for the cmake config file. if(WIN32 AND NOT CYGWIN) - set(SCRIPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/CMake") + set(INSTALL_CMAKE_DIR CMake/${PROJECT_NAME}) else() - set(SCRIPT_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/cmake") + set(INSTALL_CMAKE_DIR lib/cmake/${PROJECT_NAME}) endif() -# Configure the include directory for matlab.h -# This allows the #include to be either gtwrap/matlab.h, wrap/matlab.h or something custom. -if(NOT DEFINED GTWRAP_INCLUDE_NAME) - set(GTWRAP_INCLUDE_NAME "gtwrap" CACHE INTERNAL "Directory name for Matlab includes") -endif() -configure_file(${PROJECT_SOURCE_DIR}/templates/matlab_wrapper.tpl.in ${PROJECT_SOURCE_DIR}/gtwrap/matlab_wrapper.tpl) +set(INSTALL_LIB_DIR lib/${PROJECT_NAME}) +set(INSTALL_BIN_DIR bin/${PROJECT_NAME}) +set(INSTALL_INCLUDE_DIR include/${PROJECT_NAME}) +# ############################################################################## +# Package Configuration + +# Helper functions for generating the gtwrapConfig.cmake file correctly. +include(CMakePackageConfigHelpers) + +# Configure the config file which is used for `find_package`. +configure_package_config_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/gtwrapConfig.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/cmake/gtwrapConfig.cmake + INSTALL_DESTINATION "${INSTALL_CMAKE_DIR}" + PATH_VARS INSTALL_CMAKE_DIR INSTALL_LIB_DIR INSTALL_BIN_DIR + INSTALL_INCLUDE_DIR + INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) + +message(STATUS "Package config : ${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}") + +# ############################################################################## +# Install the package + +message(STATUS "CMake : ${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}") # Install CMake scripts to the standard CMake script directory. -install(FILES cmake/gtwrapConfig.cmake cmake/MatlabWrap.cmake - cmake/PybindWrap.cmake cmake/GtwrapUtils.cmake - DESTINATION "${SCRIPT_INSTALL_DIR}/gtwrap") +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/cmake/gtwrapConfig.cmake + cmake/MatlabWrap.cmake cmake/PybindWrap.cmake cmake/GtwrapUtils.cmake + DESTINATION "${CMAKE_INSTALL_PREFIX}/${INSTALL_CMAKE_DIR}") -# Needed for the CMAKE_INSTALL_X variables used below. -include(GNUInstallDirs) +# Configure the include directory for matlab.h This allows the #include to be +# either gtwrap/matlab.h, wrap/matlab.h or something custom. +if(NOT DEFINED GTWRAP_INCLUDE_NAME) + set(GTWRAP_INCLUDE_NAME + "gtwrap" + CACHE INTERNAL "Directory name for Matlab includes") +endif() + +configure_file(${PROJECT_SOURCE_DIR}/templates/matlab_wrapper.tpl.in + ${PROJECT_SOURCE_DIR}/gtwrap/matlab_wrapper.tpl) # Install the gtwrap python package as a directory so it can be found by CMake # for wrapping. -install(DIRECTORY gtwrap DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/gtwrap") +message(STATUS "Lib path : ${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}") +install(DIRECTORY gtwrap + DESTINATION "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}") + +# Install pybind11 directory to `CMAKE_INSTALL_PREFIX/lib/gtwrap/pybind11` This +# will allow the gtwrapConfig.cmake file to load it later. +install(DIRECTORY pybind11 + DESTINATION "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIB_DIR}") # Install wrapping scripts as binaries to `CMAKE_INSTALL_PREFIX/bin` so they can # be invoked for wrapping. We use DESTINATION (instead of TYPE) so we can # support older CMake versions. +message(STATUS "Bin path : ${CMAKE_INSTALL_PREFIX}/${INSTALL_BIN_DIR}") install(PROGRAMS scripts/pybind_wrap.py scripts/matlab_wrap.py - DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}) - -# Install pybind11 directory to `CMAKE_INSTALL_PREFIX/lib/gtwrap/pybind11` This -# will allow the gtwrapConfig.cmake file to load it later. -install(DIRECTORY pybind11 DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}/gtwrap") + DESTINATION "${CMAKE_INSTALL_PREFIX}/${INSTALL_BIN_DIR}") # Install the matlab.h file to `CMAKE_INSTALL_PREFIX/lib/gtwrap/matlab.h`. -install(FILES matlab.h DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/gtwrap") +message( + STATUS "Header path : ${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}") +install(FILES matlab.h + DESTINATION "${CMAKE_INSTALL_PREFIX}/${INSTALL_INCLUDE_DIR}") diff --git a/DOCS.md b/DOCS.md index a7e8d8e3e..00104c123 100644 --- a/DOCS.md +++ b/DOCS.md @@ -51,6 +51,17 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the - Class variables are read-write so they can be updated directly in Python. +- Operator Overloading (Python only) + - You can overload operators just like in C++. + + ```cpp + class Overload { + Overload operator*(const Overload& other) const; + }; + ``` + - Supported operators are the intersection of those supported in C++ and in Python. + - Operator overloading definitions have to be marked as `const` methods. + - Pointer types - To declare a simple/raw pointer, simply add an `@` to the class name, e.g.`Pose3@`. - To declare a shared pointer (e.g. `gtsam::noiseModel::Base::shared_ptr`), use an asterisk (i.e. `*`). E.g. `gtsam::noiseModel::Base*` to define the wrapping for the `Base` noise model shared pointer. @@ -78,7 +89,7 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the - Can have multiple functions of the same name in different namespaces. - Functions can be templated and have multiple template arguments, e.g. ```cpp - template + template ``` - Using classes defined in other modules @@ -99,7 +110,7 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the virtual boost::shared_ptr clone() const; ``` -- Class Templates +- Templates - Basic templates are supported either with an explicit list of types to instantiate, e.g. @@ -113,18 +124,31 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the template class Class2 { ... }; typedef Class2 MyInstantiatedClass; ``` - + - Templates can also be defined for methods, properties and static methods. - In the class definition, appearances of the template argument(s) will be replaced with their instantiated types, e.g. `void setValue(const T& value);`. - To refer to the instantiation of the template class itself, use `This`, i.e. `static This Create();`. - To create new instantiations in other modules, you must copy-and-paste the whole class definition into the new module, but use only your new instantiation types. - - When forward-declaring template instantiations, use the generated/typedefed name, e.g. + - When forward-declaring template instantiations, use the generated/typedef'd name, e.g. ```cpp class gtsam::Class1Pose2; class gtsam::MyInstantiatedClass; ``` + - Template arguments can be templates themselves, e.g. + + ```cpp + // Typedef'd PinholeCamera + template + class PinholeCamera { ... }; + typedef gtsam::PinholeCamera PinholeCameraCal3_S2; + + template + class SfmFactor { ... }; + // This is valid. + typedef gtsam::SfmFactor> BasicSfmFactor; + ``` - `Boost.serialization` within the wrapper: - You need to mark classes as being serializable in the markup file (see `gtsam.i` for examples). diff --git a/cmake/GtwrapUtils.cmake b/cmake/GtwrapUtils.cmake index a3a77708c..8479015dc 100644 --- a/cmake/GtwrapUtils.cmake +++ b/cmake/GtwrapUtils.cmake @@ -63,9 +63,10 @@ macro(configure_python_variables) endmacro() # Set the Python version for the wrapper and set the paths to the executable and -# include/library directories. WRAP_PYTHON_VERSION can be "Default" or a +# include/library directories. +# WRAP_PYTHON_VERSION (optionally) can be "Default" or a # specific major.minor version. -macro(gtwrap_get_python_version WRAP_PYTHON_VERSION) +macro(gtwrap_get_python_version) # Unset these cached variables to avoid surprises when the python in the # current environment are different from the cached! unset(Python_EXECUTABLE CACHE) @@ -74,6 +75,11 @@ macro(gtwrap_get_python_version WRAP_PYTHON_VERSION) unset(Python_VERSION_MINOR CACHE) unset(Python_VERSION_PATCH CACHE) + # Set default value if the parameter is not passed in + if(NOT WRAP_PYTHON_VERSION) + set(WRAP_PYTHON_VERSION "Default") + endif() + # Allow override if(${WRAP_PYTHON_VERSION} STREQUAL "Default") # Check for Python3 or Python2 in order diff --git a/cmake/MatlabWrap.cmake b/cmake/MatlabWrap.cmake index 75654238a..083b88566 100644 --- a/cmake/MatlabWrap.cmake +++ b/cmake/MatlabWrap.cmake @@ -1,59 +1,70 @@ -find_package( - Matlab - COMPONENTS MEX_COMPILER - REQUIRED) - -if(NOT Matlab_MEX_COMPILER) - message( - FATAL_ERROR - "Cannot find MEX compiler binary. Please check your Matlab installation and ensure MEX in installed as well." - ) +if(GTWRAP_PYTHON_PACKAGE_DIR) + # packaged + set(GTWRAP_PACKAGE_DIR "${GTWRAP_PYTHON_PACKAGE_DIR}") +else() + set(GTWRAP_PACKAGE_DIR ${CMAKE_CURRENT_LIST_DIR}/..) endif() -if(WRAP_BUILD_TYPE_POSTFIXES) - set(CURRENT_POSTFIX ${CMAKE_${CMAKE_BUILD_TYPE_UPPER}_POSTFIX}) -endif() +# Macro which finds and configure Matlab before we do any wrapping. +macro(find_and_configure_matlab) + find_package( + Matlab + COMPONENTS MEX_COMPILER + REQUIRED) -# WRAP_MEX_BUILD_STATIC_MODULE is not for Windows - on Windows any static -# are already compiled into the library by the linker -if(WRAP_MEX_BUILD_STATIC_MODULE AND WIN32) - message(FATAL_ERROR "WRAP_MEX_BUILD_STATIC_MODULE should not be set on Windows - the linker already automatically compiles in any dependent static libraries. To create a standalone toolbox pacakge, simply ensure that CMake finds the static versions of all dependent libraries (Boost, etc).") -endif() - -set(MEX_COMMAND ${Matlab_MEX_COMPILER} CACHE PATH "Path to MATLAB MEX compiler") -set(MATLAB_ROOT ${Matlab_ROOT_DIR} CACHE PATH "Path to MATLAB installation root (e.g. /usr/local/MATLAB/R2012a)") - -# Try to automatically configure mex path from provided custom `bin` path. -if(WRAP_CUSTOM_MATLAB_PATH) - set(matlab_bin_directory ${WRAP_CUSTOM_MATLAB_PATH}) - - if(WIN32) - set(mex_program_name "mex.bat") - else() - set(mex_program_name "mex") + if(NOT Matlab_MEX_COMPILER) + message( + FATAL_ERROR + "Cannot find MEX compiler binary. Please check your Matlab installation and ensure MEX in installed as well." + ) endif() - # Run find_program explicitly putting $PATH after our predefined program - # directories using 'ENV PATH' and 'NO_SYSTEM_ENVIRONMENT_PATH' - this prevents - # finding the LaTeX mex program (totally unrelated to MATLAB Mex) when LaTeX is - # on the system path. - find_program(MEX_COMMAND ${mex_program_name} - PATHS ${matlab_bin_directory} ENV PATH - NO_DEFAULT_PATH) - mark_as_advanced(FORCE MEX_COMMAND) - # Now that we have mex, trace back to find the Matlab installation root - get_filename_component(MEX_COMMAND "${MEX_COMMAND}" REALPATH) - get_filename_component(mex_path "${MEX_COMMAND}" PATH) - if(mex_path MATCHES ".*/win64$") - get_filename_component(MATLAB_ROOT "${mex_path}/../.." ABSOLUTE) - else() - get_filename_component(MATLAB_ROOT "${mex_path}/.." ABSOLUTE) + if(WRAP_BUILD_TYPE_POSTFIXES) + set(CURRENT_POSTFIX ${CMAKE_${CMAKE_BUILD_TYPE_UPPER}_POSTFIX}) endif() -endif() + + # WRAP_MEX_BUILD_STATIC_MODULE is not for Windows - on Windows any static + # are already compiled into the library by the linker + if(WRAP_MEX_BUILD_STATIC_MODULE AND WIN32) + message(FATAL_ERROR "WRAP_MEX_BUILD_STATIC_MODULE should not be set on Windows - the linker already automatically compiles in any dependent static libraries. To create a standalone toolbox pacakge, simply ensure that CMake finds the static versions of all dependent libraries (Boost, etc).") + endif() + + set(MEX_COMMAND ${Matlab_MEX_COMPILER} CACHE PATH "Path to MATLAB MEX compiler") + set(MATLAB_ROOT ${Matlab_ROOT_DIR} CACHE PATH "Path to MATLAB installation root (e.g. /usr/local/MATLAB/R2012a)") + + # Try to automatically configure mex path from provided custom `bin` path. + if(WRAP_CUSTOM_MATLAB_PATH) + set(matlab_bin_directory ${WRAP_CUSTOM_MATLAB_PATH}) + + if(WIN32) + set(mex_program_name "mex.bat") + else() + set(mex_program_name "mex") + endif() + + # Run find_program explicitly putting $PATH after our predefined program + # directories using 'ENV PATH' and 'NO_SYSTEM_ENVIRONMENT_PATH' - this prevents + # finding the LaTeX mex program (totally unrelated to MATLAB Mex) when LaTeX is + # on the system path. + find_program(MEX_COMMAND ${mex_program_name} + PATHS ${matlab_bin_directory} ENV PATH + NO_DEFAULT_PATH) + mark_as_advanced(FORCE MEX_COMMAND) + # Now that we have mex, trace back to find the Matlab installation root + get_filename_component(MEX_COMMAND "${MEX_COMMAND}" REALPATH) + get_filename_component(mex_path "${MEX_COMMAND}" PATH) + if(mex_path MATCHES ".*/win64$") + get_filename_component(MATLAB_ROOT "${mex_path}/../.." ABSOLUTE) + else() + get_filename_component(MATLAB_ROOT "${mex_path}/.." ABSOLUTE) + endif() + endif() +endmacro() # Consistent and user-friendly wrap function function(matlab_wrap interfaceHeader linkLibraries extraIncludeDirs extraMexFlags ignore_classes) + find_and_configure_matlab() wrap_and_install_library("${interfaceHeader}" "${linkLibraries}" "${extraIncludeDirs}" "${extraMexFlags}" "${ignore_classes}") diff --git a/cmake/gtwrapConfig.cmake b/cmake/gtwrapConfig.cmake deleted file mode 100644 index d64efa048..000000000 --- a/cmake/gtwrapConfig.cmake +++ /dev/null @@ -1,32 +0,0 @@ -# This config file modifies CMAKE_MODULE_PATH so that the wrap cmake files may -# be included This file also allows the use of `find_package(gtwrap)` in CMake. - -# Standard includes -include(GNUInstallDirs) -include(CMakePackageConfigHelpers) -include(CMakeDependentOption) - -set(GTWRAP_DIR "${CMAKE_CURRENT_LIST_DIR}") - -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") - -if(WIN32 AND NOT CYGWIN) - set(GTWRAP_CMAKE_DIR "${GTWRAP_DIR}") - set(GTWRAP_SCRIPT_DIR ${CMAKE_INSTALL_FULL_BINDIR}) - set(GTWRAP_PYTHON_PACKAGE_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/gtwrap) -else() - set(GTWRAP_CMAKE_DIR "${GTWRAP_DIR}") - set(GTWRAP_SCRIPT_DIR ${CMAKE_INSTALL_FULL_BINDIR}) - set(GTWRAP_PYTHON_PACKAGE_DIR ${CMAKE_INSTALL_FULL_LIBDIR}/gtwrap) -endif() - -# Load all the CMake scripts from the standard location -include(${GTWRAP_CMAKE_DIR}/PybindWrap.cmake) -include(${GTWRAP_CMAKE_DIR}/GtwrapUtils.cmake) - -# Set the variables for the wrapping scripts to be used in the build. -set(PYBIND_WRAP_SCRIPT "${GTWRAP_SCRIPT_DIR}/pybind_wrap.py") -set(MATLAB_WRAP_SCRIPT "${GTWRAP_SCRIPT_DIR}/matlab_wrap.py") - -# Load the pybind11 code from the library installation path -add_subdirectory(${CMAKE_INSTALL_FULL_LIBDIR}/gtwrap/pybind11 pybind11) diff --git a/cmake/gtwrapConfig.cmake.in b/cmake/gtwrapConfig.cmake.in new file mode 100644 index 000000000..5565a867a --- /dev/null +++ b/cmake/gtwrapConfig.cmake.in @@ -0,0 +1,24 @@ +# This config file modifies CMAKE_MODULE_PATH so that the wrap cmake files may +# be included This file also allows the use of `find_package(gtwrap)` in CMake. + +@PACKAGE_INIT@ + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") + +# Set the path to the Python package directory so we can add it to the PYTHONPATH. +# Used in the *Wrap.cmake files. +set_and_check(GTWRAP_PYTHON_PACKAGE_DIR @PACKAGE_INSTALL_LIB_DIR@) + +# Load all the CMake scripts from the standard location +include(@PACKAGE_INSTALL_CMAKE_DIR@/PybindWrap.cmake) +include(@PACKAGE_INSTALL_CMAKE_DIR@/MatlabWrap.cmake) +include(@PACKAGE_INSTALL_CMAKE_DIR@/GtwrapUtils.cmake) + +# Set the variables for the wrapping scripts to be used in the build. +set_and_check(PYBIND_WRAP_SCRIPT "@PACKAGE_INSTALL_BIN_DIR@/pybind_wrap.py") +set_and_check(MATLAB_WRAP_SCRIPT "@PACKAGE_INSTALL_BIN_DIR@/matlab_wrap.py") + +# Load the pybind11 code from the library installation path +add_subdirectory(@PACKAGE_INSTALL_LIB_DIR@/pybind11 pybind11) + +check_required_components(gtwrap) diff --git a/gtwrap/interface_parser/classes.py b/gtwrap/interface_parser/classes.py index 7332e0bfe..e2c28d8ed 100644 --- a/gtwrap/interface_parser/classes.py +++ b/gtwrap/interface_parser/classes.py @@ -10,15 +10,15 @@ Parser classes and rules for parsing C++ classes. Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert """ -from typing import List, Union +from typing import Iterable, List, Union -from pyparsing import Optional, ZeroOrMore +from pyparsing import Optional, ZeroOrMore, Literal from .function import ArgumentList, ReturnType from .template import Template from .tokens import (CLASS, COLON, CONST, IDENT, LBRACE, LPAREN, RBRACE, - RPAREN, SEMI_COLON, STATIC, VIRTUAL) -from .type import Type, Typename + RPAREN, SEMI_COLON, STATIC, VIRTUAL, OPERATOR) +from .type import TemplatedType, Type, Typename class Method: @@ -148,13 +148,13 @@ class Property: ```` """ rule = ( - Type.rule("ctype") # + (Type.rule ^ TemplatedType.rule)("ctype") # + IDENT("name") # + SEMI_COLON # ).setParseAction(lambda t: Property(t.ctype, t.name)) def __init__(self, ctype: Type, name: str, parent=''): - self.ctype = ctype + self.ctype = ctype[0] # ParseResult is a list self.name = name self.parent = parent @@ -162,6 +162,69 @@ class Property: return '{} {}'.format(self.ctype.__repr__(), self.name) +class Operator: + """ + Rule for parsing operator overloads. + + E.g. + ``` + class Overload { + Vector2 operator+(const Vector2 &v) const; + }; + """ + rule = ( + ReturnType.rule("return_type") # + + Literal("operator")("name") # + + OPERATOR("operator") # + + LPAREN # + + ArgumentList.rule("args_list") # + + RPAREN # + + CONST("is_const") # + + SEMI_COLON # BR + ).setParseAction(lambda t: Operator(t.name, t.operator, t.return_type, t. + args_list, t.is_const)) + + def __init__(self, + name: str, + operator: str, + return_type: ReturnType, + args: ArgumentList, + is_const: str, + parent: Union[str, "Class"] = ''): + self.name = name + self.operator = operator + self.return_type = return_type + self.args = args + self.is_const = is_const + self.is_unary = len(args) == 0 + + self.parent = parent + + # Check for valid unary operators + if self.is_unary and self.operator not in ('+', '-'): + raise ValueError("Invalid unary operator {} used for {}".format( + self.operator, self)) + + # Check that number of arguments are either 0 or 1 + assert 0 <= len(args) < 2, \ + "Operator overload should be at most 1 argument, " \ + "{} arguments provided".format(len(args)) + + # Check to ensure arg and return type are the same. + if len(args) == 1 and self.operator not in ("()", "[]"): + assert args.args_list[0].ctype.typename.name == return_type.type1.typename.name, \ + "Mixed type overloading not supported. Both arg and return type must be the same." + + def __repr__(self) -> str: + return "Operator: {}{}{}({}) {}".format( + self.return_type, + self.name, + self.operator, + self.args, + self.is_const, + ) + + def collect_namespaces(obj): """ Get the chain of namespaces from the lowest to highest for the given object. @@ -188,21 +251,23 @@ class Class: }; ``` """ - class MethodsAndProperties: + class Members: """ - Rule for all the methods and properties within a class. + Rule for all the members within a class. """ rule = ZeroOrMore(Constructor.rule ^ StaticMethod.rule ^ Method.rule - ^ Property.rule).setParseAction( - lambda t: Class.MethodsAndProperties(t.asList())) + ^ Property.rule ^ Operator.rule).setParseAction( + lambda t: Class.Members(t.asList())) - def __init__(self, methods_props: List[Union[Constructor, Method, - StaticMethod, Property]]): + def __init__(self, + members: List[Union[Constructor, Method, StaticMethod, + Property, Operator]]): self.ctors = [] self.methods = [] self.static_methods = [] self.properties = [] - for m in methods_props: + self.operators = [] + for m in members: if isinstance(m, Constructor): self.ctors.append(m) elif isinstance(m, Method): @@ -211,6 +276,8 @@ class Class: self.static_methods.append(m) elif isinstance(m, Property): self.properties.append(m) + elif isinstance(m, Operator): + self.operators.append(m) _parent = COLON + Typename.rule("parent_class") rule = ( @@ -220,7 +287,7 @@ class Class: + IDENT("name") # + Optional(_parent) # + LBRACE # - + MethodsAndProperties.rule("methods_props") # + + Members.rule("members") # + RBRACE # + SEMI_COLON # BR ).setParseAction(lambda t: Class( @@ -228,10 +295,11 @@ class Class: t.is_virtual, t.name, t.parent_class, - t.methods_props.ctors, - t.methods_props.methods, - t.methods_props.static_methods, - t.methods_props.properties, + t.members.ctors, + t.members.methods, + t.members.static_methods, + t.members.properties, + t.members.operators, )) def __init__( @@ -244,13 +312,18 @@ class Class: methods: List[Method], static_methods: List[StaticMethod], properties: List[Property], + operators: List[Operator], parent: str = '', ): self.template = template self.is_virtual = is_virtual self.name = name if parent_class: - self.parent_class = Typename.from_parse_result(parent_class) + if isinstance(parent_class, Iterable): + self.parent_class = parent_class[0] + else: + self.parent_class = parent_class + else: self.parent_class = '' @@ -258,7 +331,9 @@ class Class: self.methods = methods self.static_methods = static_methods self.properties = properties + self.operators = operators self.parent = parent + # Make sure ctors' names and class name are the same. for ctor in self.ctors: if ctor.name != self.name: diff --git a/gtwrap/interface_parser/declaration.py b/gtwrap/interface_parser/declaration.py index ad0b9d8d9..2a916899d 100644 --- a/gtwrap/interface_parser/declaration.py +++ b/gtwrap/interface_parser/declaration.py @@ -48,7 +48,7 @@ class ForwardDeclaration: parent: str = ''): self.name = name if parent_type: - self.parent_type = Typename.from_parse_result(parent_type) + self.parent_type = parent_type else: self.parent_type = '' diff --git a/gtwrap/interface_parser/function.py b/gtwrap/interface_parser/function.py index 453577e58..526d5e055 100644 --- a/gtwrap/interface_parser/function.py +++ b/gtwrap/interface_parser/function.py @@ -10,14 +10,14 @@ Parser classes and rules for parsing C++ functions. Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert """ -from typing import List, Union +from typing import Iterable, List, Union from pyparsing import Optional, ParseResults, delimitedList from .template import Template from .tokens import (COMMA, IDENT, LOPBRACK, LPAREN, PAIR, ROPBRACK, RPAREN, SEMI_COLON) -from .type import Type +from .type import TemplatedType, Type class Argument: @@ -29,16 +29,23 @@ class Argument: void sayHello(/*`s` is the method argument with type `const string&`*/ const string& s); ``` """ - rule = (Type.rule("ctype") + + rule = ((Type.rule ^ TemplatedType.rule)("ctype") + IDENT("name")).setParseAction(lambda t: Argument(t.ctype, t.name)) - def __init__(self, ctype: Type, name: str): - self.ctype = ctype + def __init__(self, ctype: Union[Type, TemplatedType], name: str): + if isinstance(ctype, Iterable): + self.ctype = ctype[0] + else: + self.ctype = ctype self.name = name self.parent: Union[ArgumentList, None] = None def __repr__(self) -> str: - return '{} {}'.format(self.ctype.__repr__(), self.name) + return self.to_cpp() + + def to_cpp(self) -> str: + """Return full C++ representation of argument.""" + return '{} {}'.format(repr(self.ctype), self.name) class ArgumentList: @@ -93,11 +100,13 @@ class ReturnType: + Type.rule("type2") # + ROPBRACK # ) - rule = (_pair ^ Type.rule("type1")).setParseAction( # BR - lambda t: ReturnType(t.type1, t.type2)) + rule = (_pair ^ + (Type.rule ^ TemplatedType.rule)("type1")).setParseAction( # BR + lambda t: ReturnType(t.type1, t.type2)) - def __init__(self, type1: Type, type2: Type): - self.type1 = type1 + def __init__(self, type1: Union[Type, TemplatedType], type2: Type): + # If a TemplatedType, the return is a ParseResults, so we extract out the type. + self.type1 = type1[0] if isinstance(type1, ParseResults) else type1 self.type2 = type2 # The parent object which contains the return type # E.g. Method, StaticMethod, Template, Constructor, GlobalFunction diff --git a/gtwrap/interface_parser/template.py b/gtwrap/interface_parser/template.py index 99e929d39..dc9d0ce44 100644 --- a/gtwrap/interface_parser/template.py +++ b/gtwrap/interface_parser/template.py @@ -16,7 +16,7 @@ from pyparsing import Optional, ParseResults, delimitedList from .tokens import (EQUAL, IDENT, LBRACE, LOPBRACK, RBRACE, ROPBRACK, SEMI_COLON, TEMPLATE, TYPEDEF) -from .type import Typename +from .type import Typename, TemplatedType class Template: @@ -38,7 +38,8 @@ class Template: + Optional( # EQUAL # + LBRACE # - + ((delimitedList(Typename.rule)("instantiations"))) # + + ((delimitedList(TemplatedType.rule ^ Typename.rule) + ("instantiations"))) # + RBRACE # )).setParseAction(lambda t: Template.TypenameAndInstantiations( t.typename, t.instantiations)) @@ -46,10 +47,12 @@ class Template: def __init__(self, typename: str, instantiations: ParseResults): self.typename = typename + self.instantiations = [] if instantiations: - self.instantiations = instantiations.asList() - else: - self.instantiations = [] + for inst in instantiations: + x = inst.typename if isinstance(inst, + TemplatedType) else inst + self.instantiations.append(x) rule = ( # BR TEMPLATE # @@ -80,11 +83,19 @@ class TypedefTemplateInstantiation: typedef SuperComplexName EasierName; ``` """ - rule = (TYPEDEF + Typename.rule("typename") + IDENT("new_name") + + rule = (TYPEDEF + TemplatedType.rule("templated_type") + + IDENT("new_name") + SEMI_COLON).setParseAction(lambda t: TypedefTemplateInstantiation( - Typename.from_parse_result(t.typename), t.new_name)) + t.templated_type[0], t.new_name)) - def __init__(self, typename: Typename, new_name: str, parent: str = ''): - self.typename = typename + def __init__(self, + templated_type: TemplatedType, + new_name: str, + parent: str = ''): + self.typename = templated_type.typename self.new_name = new_name self.parent = parent + + def __repr__(self): + return "Typedef: {new_name} = {typename}".format( + new_name=self.new_name, typename=self.typename) diff --git a/gtwrap/interface_parser/tokens.py b/gtwrap/interface_parser/tokens.py index 6653812c4..432c5407a 100644 --- a/gtwrap/interface_parser/tokens.py +++ b/gtwrap/interface_parser/tokens.py @@ -10,7 +10,7 @@ All the token definitions. Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert """ -from pyparsing import Keyword, Literal, Suppress, Word, alphanums, alphas, nums +from pyparsing import Keyword, Literal, Suppress, Word, alphanums, alphas, nums, Or # rule for identifiers (e.g. variable names) IDENT = Word(alphas + '_', alphanums + '_') ^ Word(nums) @@ -46,3 +46,42 @@ BASIS_TYPES = map( "float", ], ) + +OPERATOR = Or( + map( + Literal, + [ + '+', # __add__, __pos__ + '-', # __sub__, __neg__ + '*', # __mul__ + '/', # __truediv__ + '%', # __mod__ + '^', # __xor__ + '&', # __and__ + '|', # __or__ + # '~', # __invert__ + '+=', # __iadd__ + '-=', # __isub__ + '*=', # __imul__ + '/=', # __itruediv__ + '%=', # __imod__ + '^=', # __ixor__ + '&=', # __iand__ + '|=', # __ior__ + '<<', # __lshift__ + '<<=', # __ilshift__ + '>>', # __rshift__ + '>>=', # __irshift__ + '==', # __eq__ + '!=', # __ne__ + '<', # __lt__ + '>', # __gt__ + '<=', # __le__ + '>=', # __ge__ + # '!', # Use `not` in python + # '&&', # Use `and` in python + # '||', # Use `or` in python + '()', # __call__ + '[]', # __getitem__ + ], + )) diff --git a/gtwrap/interface_parser/type.py b/gtwrap/interface_parser/type.py index 4578b9f37..e4b80a224 100644 --- a/gtwrap/interface_parser/type.py +++ b/gtwrap/interface_parser/type.py @@ -12,7 +12,7 @@ Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellae # pylint: disable=unnecessary-lambda, expression-not-assigned -from typing import Iterable, Union +from typing import Iterable, List, Union from pyparsing import Forward, Optional, Or, ParseResults, delimitedList @@ -42,20 +42,15 @@ class Typename: namespaces_name_rule = delimitedList(IDENT, "::") instantiation_name_rule = delimitedList(IDENT, "::") - rule = Forward() - rule << ( + rule = ( namespaces_name_rule("namespaces_and_name") # - + Optional( - (LOPBRACK + delimitedList(rule, ",") - ("instantiations") + ROPBRACK))).setParseAction( - lambda t: Typename(t.namespaces_and_name, t.instantiations)) + ).setParseAction(lambda t: Typename(t)) def __init__(self, - namespaces_and_name: ParseResults, + t: ParseResults, instantiations: Union[tuple, list, str, ParseResults] = ()): - self.name = namespaces_and_name[ - -1] # the name is the last element in this list - self.namespaces = namespaces_and_name[:-1] + self.name = t[-1] # the name is the last element in this list + self.namespaces = t[:-1] if instantiations: if isinstance(instantiations, Iterable): @@ -83,6 +78,10 @@ class Typename: res += instantiation.instantiated_name() return res + def qualified_name(self): + """Return the fully qualified name, e.g. `gtsam::internal::PoseKey`.""" + return "::".join(self.namespaces + [self.name]) + def to_cpp(self) -> str: """Generate the C++ code for wrapping.""" idx = 1 if self.namespaces and not self.namespaces[0] else 0 @@ -108,72 +107,76 @@ class Typename: return not res -class QualifiedType: - """Type with qualifiers, such as `const`.""" - - rule = ( - Typename.rule("typename") # - + Optional( - SHARED_POINTER("is_shared_ptr") | RAW_POINTER("is_ptr") - | REF("is_ref"))).setParseAction(lambda t: QualifiedType(t)) - - def __init__(self, t: ParseResults): - self.typename = Typename.from_parse_result(t.typename) - self.is_shared_ptr = t.is_shared_ptr - self.is_ptr = t.is_ptr - self.is_ref = t.is_ref - - -class BasisType: +class BasicType: """ - Basis types are the built-in types in C++ such as double, int, char, etc. + Basic types are the fundamental built-in types in C++ such as double, int, char, etc. When using templates, the basis type will take on the same form as the template. E.g. - ``` - template - void func(const T& x); - ``` + ``` + template + void func(const T& x); + ``` - will give + will give - ``` - m_.def("CoolFunctionDoubleDouble",[](const double& s) { - return wrap_example::CoolFunction(s); - }, py::arg("s")); - ``` + ``` + m_.def("CoolFunctionDoubleDouble",[](const double& s) { + return wrap_example::CoolFunction(s); + }, py::arg("s")); + ``` """ - rule = ( - Or(BASIS_TYPES)("typename") # - + Optional( - SHARED_POINTER("is_shared_ptr") | RAW_POINTER("is_ptr") - | REF("is_ref")) # - ).setParseAction(lambda t: BasisType(t)) + rule = (Or(BASIS_TYPES)("typename")).setParseAction(lambda t: BasicType(t)) def __init__(self, t: ParseResults): - self.typename = Typename([t.typename]) - self.is_ptr = t.is_ptr - self.is_shared_ptr = t.is_shared_ptr - self.is_ref = t.is_ref + self.typename = Typename(t.asList()) + + +class CustomType: + """ + Custom defined types with the namespace. + Essentially any C++ data type that is not a BasicType. + + E.g. + ``` + gtsam::Matrix wTc; + ``` + + Here `gtsam::Matrix` is a custom type. + """ + + rule = (Typename.rule("typename")).setParseAction(lambda t: CustomType(t)) + + def __init__(self, t: ParseResults): + self.typename = Typename(t) class Type: - """The type value that is parsed, e.g. void, string, size_t.""" + """ + Parsed datatype, can be either a fundamental type or a custom datatype. + E.g. void, double, size_t, Matrix. + + The type can optionally be a raw pointer, shared pointer or reference. + Can also be optionally qualified with a `const`, e.g. `const int`. + """ rule = ( Optional(CONST("is_const")) # - + (BasisType.rule("basis") | QualifiedType.rule("qualified")) # BR + + (BasicType.rule("basis") | CustomType.rule("qualified")) # BR + + Optional( + SHARED_POINTER("is_shared_ptr") | RAW_POINTER("is_ptr") + | REF("is_ref")) # ).setParseAction(lambda t: Type.from_parse_result(t)) def __init__(self, typename: Typename, is_const: str, is_shared_ptr: str, - is_ptr: str, is_ref: str, is_basis: bool): + is_ptr: str, is_ref: str, is_basic: bool): self.typename = typename self.is_const = is_const self.is_shared_ptr = is_shared_ptr self.is_ptr = is_ptr self.is_ref = is_ref - self.is_basis = is_basis + self.is_basic = is_basic @staticmethod def from_parse_result(t: ParseResults): @@ -182,26 +185,26 @@ class Type: return Type( typename=t.basis.typename, is_const=t.is_const, - is_shared_ptr=t.basis.is_shared_ptr, - is_ptr=t.basis.is_ptr, - is_ref=t.basis.is_ref, - is_basis=True, + is_shared_ptr=t.is_shared_ptr, + is_ptr=t.is_ptr, + is_ref=t.is_ref, + is_basic=True, ) elif t.qualified: return Type( typename=t.qualified.typename, is_const=t.is_const, - is_shared_ptr=t.qualified.is_shared_ptr, - is_ptr=t.qualified.is_ptr, - is_ref=t.qualified.is_ref, - is_basis=False, + is_shared_ptr=t.is_shared_ptr, + is_ptr=t.is_ptr, + is_ref=t.is_ref, + is_basic=False, ) else: raise ValueError("Parse result is not a Type") def __repr__(self) -> str: - return "{self.typename} " \ - "{self.is_const}{self.is_shared_ptr}{self.is_ptr}{self.is_ref}".format( + return "{self.is_const} {self.typename} " \ + "{self.is_shared_ptr}{self.is_ptr}{self.is_ref}".format( self=self) def to_cpp(self, use_boost: bool) -> str: @@ -210,12 +213,14 @@ class Type: Treat all pointers as "const shared_ptr&" Treat Matrix and Vector as "const Matrix&" and "const Vector&" resp. + + Args: + use_boost: Flag indicating whether to use boost::shared_ptr or std::shared_ptr. """ shared_ptr_ns = "boost" if use_boost else "std" if self.is_shared_ptr: - # always pass by reference: https://stackoverflow.com/a/8741626/1236990 - typename = "{ns}::shared_ptr<{typename}>&".format( + typename = "{ns}::shared_ptr<{typename}>".format( ns=shared_ptr_ns, typename=self.typename.to_cpp()) elif self.is_ptr: typename = "{typename}*".format(typename=self.typename.to_cpp()) @@ -230,3 +235,81 @@ class Type: (self.is_const or self.typename.name in ["Matrix", "Vector"]) else "", typename=typename)) + + +class TemplatedType: + """ + Parser rule for data types which are templated. + This is done so that the template parameters can be pointers/references. + + E.g. std::vector, BearingRange + """ + + rule = Forward() + rule << ( + Optional(CONST("is_const")) # + + Typename.rule("typename") # + + ( + LOPBRACK # + + delimitedList(Type.rule ^ rule, ",")("template_params") # + + ROPBRACK) # + + Optional( + SHARED_POINTER("is_shared_ptr") | RAW_POINTER("is_ptr") + | REF("is_ref")) # + ).setParseAction(lambda t: TemplatedType.from_parse_result(t)) + + def __init__(self, typename: Typename, template_params: List[Type], + is_const: str, is_shared_ptr: str, is_ptr: str, is_ref: str): + instantiations = [param.typename for param in template_params] + # Recreate the typename but with the template params as instantiations. + self.typename = Typename(typename.namespaces + [typename.name], + instantiations) + + self.template_params = template_params + + self.is_const = is_const + self.is_shared_ptr = is_shared_ptr + self.is_ptr = is_ptr + self.is_ref = is_ref + + @staticmethod + def from_parse_result(t: ParseResults): + """Get the TemplatedType from the parser results.""" + return TemplatedType(t.typename, t.template_params, t.is_const, + t.is_shared_ptr, t.is_ptr, t.is_ref) + + def __repr__(self): + return "TemplatedType({typename.namespaces}::{typename.name})".format( + typename=self.typename) + + def to_cpp(self, use_boost: bool): + """ + Generate the C++ code for wrapping. + + Args: + use_boost: Flag indicating whether to use boost::shared_ptr or std::shared_ptr. + """ + # Use Type.to_cpp to do the heavy lifting for the template parameters. + template_args = ", ".join( + [t.to_cpp(use_boost) for t in self.template_params]) + + typename = "{typename}<{template_args}>".format( + typename=self.typename.qualified_name(), + template_args=template_args) + + shared_ptr_ns = "boost" if use_boost else "std" + if self.is_shared_ptr: + typename = "{ns}::shared_ptr<{typename}>".format(ns=shared_ptr_ns, + typename=typename) + elif self.is_ptr: + typename = "{typename}*".format(typename=typename) + elif self.is_ref or self.typename.name in ["Matrix", "Vector"]: + typename = typename = "{typename}&".format(typename=typename) + else: + pass + + return ("{const}{typename}".format( + const="const " if + (self.is_const + or self.typename.name in ["Matrix", "Vector"]) else "", + typename=typename)) diff --git a/gtwrap/pybind_wrapper.py b/gtwrap/pybind_wrapper.py index c275e575d..4b532f6e1 100755 --- a/gtwrap/pybind_wrapper.py +++ b/gtwrap/pybind_wrapper.py @@ -193,6 +193,24 @@ class PybindWrapper: )) return res + def wrap_operators(self, operators, cpp_class, prefix='\n' + ' ' * 8): + """Wrap all the overloaded operators in the `cpp_class`.""" + res = "" + template = "{prefix}.def({{0}})".format(prefix=prefix) + for op in operators: + if op.operator == "[]": # __getitem__ + res += "{prefix}.def(\"__getitem__\", &{cpp_class}::operator[])".format( + prefix=prefix, cpp_class=cpp_class) + elif op.operator == "()": # __call__ + res += "{prefix}.def(\"__call__\", &{cpp_class}::operator())".format( + prefix=prefix, cpp_class=cpp_class) + elif op.is_unary: + res += template.format("{0}py::self".format(op.operator)) + else: + res += template.format("py::self {0} py::self".format( + op.operator)) + return res + def wrap_instantiated_class(self, instantiated_class): """Wrap the class.""" module_var = self._gen_module_var(instantiated_class.namespaces()) @@ -205,12 +223,14 @@ class PybindWrapper: '{wrapped_ctors}' '{wrapped_methods}' '{wrapped_static_methods}' - '{wrapped_properties};\n'.format( + '{wrapped_properties}' + '{wrapped_operators};\n'.format( shared_ptr_type=('boost' if self.use_boost else 'std'), cpp_class=cpp_class, class_name=instantiated_class.name, - class_parent=str(instantiated_class.parent_class) + - (', ' if instantiated_class.parent_class else ''), + class_parent="{instantiated_class.parent_class}, ".format( + instantiated_class=instantiated_class) + if instantiated_class.parent_class else '', module_var=module_var, wrapped_ctors=self.wrap_ctors(instantiated_class), wrapped_methods=self.wrap_methods(instantiated_class.methods, @@ -219,7 +239,8 @@ class PybindWrapper: instantiated_class.static_methods, cpp_class), wrapped_properties=self.wrap_properties( instantiated_class.properties, cpp_class), - )) + wrapped_operators=self.wrap_operators( + instantiated_class.operators, cpp_class))) def wrap_stl_class(self, stl_class): """Wrap STL containers.""" diff --git a/gtwrap/template_instantiator.py b/gtwrap/template_instantiator.py index 5651a2a6f..f6c396a99 100644 --- a/gtwrap/template_instantiator.py +++ b/gtwrap/template_instantiator.py @@ -48,7 +48,7 @@ def instantiate_type(ctype: parser.Type, is_shared_ptr=ctype.is_shared_ptr, is_ptr=ctype.is_ptr, is_ref=ctype.is_ref, - is_basis=ctype.is_basis, + is_basic=ctype.is_basic, ) elif str_arg_typename == 'This': if instantiated_class: @@ -68,7 +68,7 @@ def instantiate_type(ctype: parser.Type, is_shared_ptr=ctype.is_shared_ptr, is_ptr=ctype.is_ptr, is_ref=ctype.is_ref, - is_basis=ctype.is_basis, + is_basic=ctype.is_basic, ) else: return ctype @@ -206,7 +206,7 @@ class InstantiatedMethod(parser.Method): """ We can only instantiate template methods with a single template parameter. """ - def __init__(self, original, instantiations: List[parser.Typename]=''): + def __init__(self, original, instantiations: List[parser.Typename] = ''): self.original = original self.instantiations = instantiations self.template = '' @@ -292,11 +292,15 @@ class InstantiatedClass(parser.Class): # This will allow the `This` keyword to be used in both templated and non-templated classes. typenames = self.original.template.typenames if self.original.template else [] - # Instantiate the constructors, static methods, properties - # and instance methods, respectively. + # Instantiate the constructors, static methods, properties, respectively. self.ctors = self.instantiate_ctors(typenames) self.static_methods = self.instantiate_static_methods(typenames) self.properties = self.instantiate_properties(typenames) + + # Instantiate all operator overloads + self.operators = self.instantiate_operators(typenames) + + # Instantiate all instance methods instantiated_methods = \ self.instantiate_class_templates_in_methods(typenames) @@ -323,6 +327,7 @@ class InstantiatedClass(parser.Class): self.methods, self.static_methods, self.properties, + self.operators, parent=self.parent, ) @@ -333,10 +338,11 @@ class InstantiatedClass(parser.Class): name=self.name, cpp_class=self.cpp_class(), parent_class=self.parent, - ctors="\n".join([ctor.__repr__() for ctor in self.ctors]), - methods="\n".join([m.__repr__() for m in self.methods]), - static_methods="\n".join([m.__repr__() + ctors="\n".join([repr(ctor) for ctor in self.ctors]), + methods="\n".join([repr(m) for m in self.methods]), + static_methods="\n".join([repr(m) for m in self.static_methods]), + operators="\n".join([repr(op) for op in self.operators]) ) def instantiate_ctors(self, typenames): @@ -435,6 +441,39 @@ class InstantiatedClass(parser.Class): )) return class_instantiated_methods + def instantiate_operators(self, typenames): + """ + Instantiate the class-level template in the operator overload. + + Args: + typenames: List of template types to instantiate. + + Return: List of methods instantiated with provided template args on the class. + """ + instantiated_operators = [] + for operator in self.original.operators: + instantiated_args = instantiate_args_list( + operator.args.args_list, + typenames, + self.instantiations, + self.cpp_typename(), + ) + instantiated_operators.append( + parser.Operator( + name=operator.name, + operator=operator.operator, + return_type=instantiate_return_type( + operator.return_type, + typenames, + self.instantiations, + self.cpp_typename(), + ), + args=parser.ArgumentList(instantiated_args), + is_const=operator.is_const, + parent=self, + )) + return instantiated_operators + def instantiate_properties(self, typenames): """ Instantiate the class properties. diff --git a/templates/pybind_wrapper.tpl.example b/templates/pybind_wrapper.tpl.example index 2260e5406..399c690ac 100644 --- a/templates/pybind_wrapper.tpl.example +++ b/templates/pybind_wrapper.tpl.example @@ -3,6 +3,7 @@ #include #include #include +#include #include "gtsam/base/serialization.h" #include "gtsam/nonlinear/utilities.h" // for RedirectCout. diff --git a/tests/expected/matlab/+gtsam/PinholeCameraCal3Bundler.m b/tests/expected/matlab/+gtsam/PinholeCameraCal3Bundler.m index 3e8451e96..f5b84943a 100644 --- a/tests/expected/matlab/+gtsam/PinholeCameraCal3Bundler.m +++ b/tests/expected/matlab/+gtsam/PinholeCameraCal3Bundler.m @@ -9,7 +9,7 @@ classdef PinholeCameraCal3Bundler < handle 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); + special_cases_wrapper(5, my_ptr); else error('Arguments do not match any overload of gtsam.PinholeCameraCal3Bundler constructor'); end @@ -17,7 +17,7 @@ classdef PinholeCameraCal3Bundler < handle end function delete(obj) - special_cases_wrapper(4, obj.ptr_gtsamPinholeCameraCal3Bundler); + special_cases_wrapper(6, obj.ptr_gtsamPinholeCameraCal3Bundler); end function display(obj), obj.print(''); end diff --git a/tests/expected/matlab/MultipleTemplatesIntDouble.m b/tests/expected/matlab/MultipleTemplatesIntDouble.m index 9218657d9..85de8002f 100644 --- a/tests/expected/matlab/MultipleTemplatesIntDouble.m +++ b/tests/expected/matlab/MultipleTemplatesIntDouble.m @@ -9,7 +9,7 @@ classdef MultipleTemplatesIntDouble < handle function obj = MultipleTemplatesIntDouble(varargin) if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682) my_ptr = varargin{2}; - class_wrapper(44, my_ptr); + class_wrapper(48, my_ptr); else error('Arguments do not match any overload of MultipleTemplatesIntDouble constructor'); end @@ -17,7 +17,7 @@ classdef MultipleTemplatesIntDouble < handle end function delete(obj) - class_wrapper(45, obj.ptr_MultipleTemplatesIntDouble); + class_wrapper(49, obj.ptr_MultipleTemplatesIntDouble); end function display(obj), obj.print(''); end diff --git a/tests/expected/matlab/MultipleTemplatesIntFloat.m b/tests/expected/matlab/MultipleTemplatesIntFloat.m index 6a6c4cb0a..90b79d560 100644 --- a/tests/expected/matlab/MultipleTemplatesIntFloat.m +++ b/tests/expected/matlab/MultipleTemplatesIntFloat.m @@ -9,7 +9,7 @@ classdef MultipleTemplatesIntFloat < handle function obj = MultipleTemplatesIntFloat(varargin) if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682) my_ptr = varargin{2}; - class_wrapper(46, my_ptr); + class_wrapper(50, my_ptr); else error('Arguments do not match any overload of MultipleTemplatesIntFloat constructor'); end @@ -17,7 +17,7 @@ classdef MultipleTemplatesIntFloat < handle end function delete(obj) - class_wrapper(47, obj.ptr_MultipleTemplatesIntFloat); + class_wrapper(51, obj.ptr_MultipleTemplatesIntFloat); end function display(obj), obj.print(''); end diff --git a/tests/expected/matlab/MyFactorPosePoint2.m b/tests/expected/matlab/MyFactorPosePoint2.m index 50bd775fa..290e41d4e 100644 --- a/tests/expected/matlab/MyFactorPosePoint2.m +++ b/tests/expected/matlab/MyFactorPosePoint2.m @@ -12,9 +12,9 @@ classdef MyFactorPosePoint2 < handle function obj = MyFactorPosePoint2(varargin) if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682) my_ptr = varargin{2}; - class_wrapper(48, my_ptr); + class_wrapper(52, my_ptr); elseif nargin == 4 && isa(varargin{1},'numeric') && isa(varargin{2},'numeric') && isa(varargin{3},'double') && isa(varargin{4},'gtsam.noiseModel.Base') - my_ptr = class_wrapper(49, varargin{1}, varargin{2}, varargin{3}, varargin{4}); + my_ptr = class_wrapper(53, varargin{1}, varargin{2}, varargin{3}, varargin{4}); else error('Arguments do not match any overload of MyFactorPosePoint2 constructor'); end @@ -22,7 +22,7 @@ classdef MyFactorPosePoint2 < handle end function delete(obj) - class_wrapper(50, obj.ptr_MyFactorPosePoint2); + class_wrapper(54, obj.ptr_MyFactorPosePoint2); end function display(obj), obj.print(''); end diff --git a/tests/expected/matlab/MyVector12.m b/tests/expected/matlab/MyVector12.m index 7d8dd69e7..c95136cc9 100644 --- a/tests/expected/matlab/MyVector12.m +++ b/tests/expected/matlab/MyVector12.m @@ -12,9 +12,9 @@ classdef MyVector12 < handle function obj = MyVector12(varargin) if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682) my_ptr = varargin{2}; - class_wrapper(41, my_ptr); + class_wrapper(45, my_ptr); elseif nargin == 0 - my_ptr = class_wrapper(42); + my_ptr = class_wrapper(46); else error('Arguments do not match any overload of MyVector12 constructor'); end @@ -22,7 +22,7 @@ classdef MyVector12 < handle end function delete(obj) - class_wrapper(43, obj.ptr_MyVector12); + class_wrapper(47, obj.ptr_MyVector12); end function display(obj), obj.print(''); end diff --git a/tests/expected/matlab/MyVector3.m b/tests/expected/matlab/MyVector3.m index 6253a7347..fe0ec9c5f 100644 --- a/tests/expected/matlab/MyVector3.m +++ b/tests/expected/matlab/MyVector3.m @@ -12,9 +12,9 @@ classdef MyVector3 < handle function obj = MyVector3(varargin) if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682) my_ptr = varargin{2}; - class_wrapper(38, my_ptr); + class_wrapper(42, my_ptr); elseif nargin == 0 - my_ptr = class_wrapper(39); + my_ptr = class_wrapper(43); else error('Arguments do not match any overload of MyVector3 constructor'); end @@ -22,7 +22,7 @@ classdef MyVector3 < handle end function delete(obj) - class_wrapper(40, obj.ptr_MyVector3); + class_wrapper(44, obj.ptr_MyVector3); end function display(obj), obj.print(''); end diff --git a/tests/expected/matlab/PrimitiveRefDouble.m b/tests/expected/matlab/PrimitiveRefDouble.m index 15743b60a..8e8e94dc6 100644 --- a/tests/expected/matlab/PrimitiveRefDouble.m +++ b/tests/expected/matlab/PrimitiveRefDouble.m @@ -19,9 +19,9 @@ classdef PrimitiveRefDouble < handle function obj = PrimitiveRefDouble(varargin) if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682) my_ptr = varargin{2}; - class_wrapper(34, my_ptr); + class_wrapper(38, my_ptr); elseif nargin == 0 - my_ptr = class_wrapper(35); + my_ptr = class_wrapper(39); else error('Arguments do not match any overload of PrimitiveRefDouble constructor'); end @@ -29,7 +29,7 @@ classdef PrimitiveRefDouble < handle end function delete(obj) - class_wrapper(36, obj.ptr_PrimitiveRefDouble); + class_wrapper(40, obj.ptr_PrimitiveRefDouble); end function display(obj), obj.print(''); end @@ -43,7 +43,7 @@ classdef PrimitiveRefDouble < handle % BRUTAL usage: Brutal(double t) : returns PrimitiveRefdouble % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'double') - varargout{1} = class_wrapper(37, varargin{:}); + varargout{1} = class_wrapper(41, varargin{:}); return end diff --git a/tests/expected/matlab/Test.m b/tests/expected/matlab/Test.m index 1942fbd2e..4c7b5eeab 100644 --- a/tests/expected/matlab/Test.m +++ b/tests/expected/matlab/Test.m @@ -9,6 +9,7 @@ %arg_EigenConstRef(Matrix value) : returns void %create_MixedPtrs() : returns pair< Test, Test > %create_ptrs() : returns pair< Test, Test > +%get_container() : returns std::vector %print() : returns void %return_Point2Ptr(bool value) : returns Point2 %return_Test(Test value) : returns Test @@ -26,6 +27,9 @@ %return_string(string value) : returns string %return_vector1(Vector value) : returns Vector %return_vector2(Vector value) : returns Vector +%set_container(vector container) : returns void +%set_container(vector container) : returns void +%set_container(vector container) : returns void % classdef Test < handle properties @@ -84,11 +88,21 @@ classdef Test < handle error('Arguments do not match any overload of function Test.create_ptrs'); end + function varargout = get_container(this, varargin) + % GET_CONTAINER usage: get_container() : returns std.vectorTest + % Doxygen can be found at https://gtsam.org/doxygen/ + if length(varargin) == 0 + varargout{1} = class_wrapper(17, this, varargin{:}); + return + end + error('Arguments do not match any overload of function Test.get_container'); + end + function varargout = print(this, varargin) % PRINT usage: print() : returns void % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 0 - class_wrapper(17, this, varargin{:}); + class_wrapper(18, this, varargin{:}); return end error('Arguments do not match any overload of function Test.print'); @@ -98,7 +112,7 @@ classdef Test < handle % RETURN_POINT2PTR usage: return_Point2Ptr(bool value) : returns Point2 % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'logical') - varargout{1} = class_wrapper(18, this, varargin{:}); + varargout{1} = class_wrapper(19, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_Point2Ptr'); @@ -108,7 +122,7 @@ classdef Test < handle % RETURN_TEST usage: return_Test(Test value) : returns Test % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'Test') - varargout{1} = class_wrapper(19, this, varargin{:}); + varargout{1} = class_wrapper(20, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_Test'); @@ -118,7 +132,7 @@ classdef Test < handle % RETURN_TESTPTR usage: return_TestPtr(Test value) : returns Test % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'Test') - varargout{1} = class_wrapper(20, this, varargin{:}); + varargout{1} = class_wrapper(21, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_TestPtr'); @@ -128,7 +142,7 @@ classdef Test < handle % RETURN_BOOL usage: return_bool(bool value) : returns bool % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'logical') - varargout{1} = class_wrapper(21, this, varargin{:}); + varargout{1} = class_wrapper(22, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_bool'); @@ -138,7 +152,7 @@ classdef Test < handle % RETURN_DOUBLE usage: return_double(double value) : returns double % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'double') - varargout{1} = class_wrapper(22, this, varargin{:}); + varargout{1} = class_wrapper(23, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_double'); @@ -148,7 +162,7 @@ classdef Test < handle % RETURN_FIELD usage: return_field(Test t) : returns bool % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'Test') - varargout{1} = class_wrapper(23, this, varargin{:}); + varargout{1} = class_wrapper(24, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_field'); @@ -158,7 +172,7 @@ classdef Test < handle % RETURN_INT usage: return_int(int value) : returns int % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'numeric') - varargout{1} = class_wrapper(24, this, varargin{:}); + varargout{1} = class_wrapper(25, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_int'); @@ -168,7 +182,7 @@ classdef Test < handle % RETURN_MATRIX1 usage: return_matrix1(Matrix value) : returns Matrix % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'double') - varargout{1} = class_wrapper(25, this, varargin{:}); + varargout{1} = class_wrapper(26, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_matrix1'); @@ -178,7 +192,7 @@ classdef Test < handle % RETURN_MATRIX2 usage: return_matrix2(Matrix value) : returns Matrix % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'double') - varargout{1} = class_wrapper(26, this, varargin{:}); + varargout{1} = class_wrapper(27, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_matrix2'); @@ -188,13 +202,13 @@ classdef Test < handle % RETURN_PAIR usage: return_pair(Vector v, Matrix A) : returns pair< Vector, Matrix > % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 2 && isa(varargin{1},'double') && size(varargin{1},2)==1 && isa(varargin{2},'double') - [ varargout{1} varargout{2} ] = class_wrapper(27, this, varargin{:}); + [ varargout{1} varargout{2} ] = class_wrapper(28, this, varargin{:}); return end % RETURN_PAIR usage: return_pair(Vector v) : returns pair< Vector, Matrix > % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'double') && size(varargin{1},2)==1 - [ varargout{1} varargout{2} ] = class_wrapper(28, this, varargin{:}); + [ varargout{1} varargout{2} ] = class_wrapper(29, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_pair'); @@ -204,7 +218,7 @@ classdef Test < handle % RETURN_PTRS usage: return_ptrs(Test p1, Test p2) : returns pair< Test, Test > % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 2 && isa(varargin{1},'Test') && isa(varargin{2},'Test') - [ varargout{1} varargout{2} ] = class_wrapper(29, this, varargin{:}); + [ varargout{1} varargout{2} ] = class_wrapper(30, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_ptrs'); @@ -214,7 +228,7 @@ classdef Test < handle % RETURN_SIZE_T usage: return_size_t(size_t value) : returns size_t % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'numeric') - varargout{1} = class_wrapper(30, this, varargin{:}); + varargout{1} = class_wrapper(31, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_size_t'); @@ -224,7 +238,7 @@ classdef Test < handle % RETURN_STRING usage: return_string(string value) : returns string % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'char') - varargout{1} = class_wrapper(31, this, varargin{:}); + varargout{1} = class_wrapper(32, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_string'); @@ -234,7 +248,7 @@ classdef Test < handle % RETURN_VECTOR1 usage: return_vector1(Vector value) : returns Vector % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'double') && size(varargin{1},2)==1 - varargout{1} = class_wrapper(32, this, varargin{:}); + varargout{1} = class_wrapper(33, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_vector1'); @@ -244,12 +258,34 @@ classdef Test < handle % RETURN_VECTOR2 usage: return_vector2(Vector value) : returns Vector % Doxygen can be found at https://gtsam.org/doxygen/ if length(varargin) == 1 && isa(varargin{1},'double') && size(varargin{1},2)==1 - varargout{1} = class_wrapper(33, this, varargin{:}); + varargout{1} = class_wrapper(34, this, varargin{:}); return end error('Arguments do not match any overload of function Test.return_vector2'); end + function varargout = set_container(this, varargin) + % SET_CONTAINER usage: set_container(vector container) : returns void + % Doxygen can be found at https://gtsam.org/doxygen/ + if length(varargin) == 1 && isa(varargin{1},'std.vectorTest') + class_wrapper(35, this, varargin{:}); + return + end + % SET_CONTAINER usage: set_container(vector container) : returns void + % Doxygen can be found at https://gtsam.org/doxygen/ + if length(varargin) == 1 && isa(varargin{1},'std.vectorTest') + class_wrapper(36, this, varargin{:}); + return + end + % SET_CONTAINER usage: set_container(vector container) : returns void + % Doxygen can be found at https://gtsam.org/doxygen/ + if length(varargin) == 1 && isa(varargin{1},'std.vectorTest') + class_wrapper(37, this, varargin{:}); + return + end + error('Arguments do not match any overload of function Test.set_container'); + end + end methods(Static = true) diff --git a/tests/expected/matlab/class_wrapper.cpp b/tests/expected/matlab/class_wrapper.cpp index f4c7c6af0..11eda2d96 100644 --- a/tests/expected/matlab/class_wrapper.cpp +++ b/tests/expected/matlab/class_wrapper.cpp @@ -297,14 +297,21 @@ void Test_create_ptrs_16(int nargout, mxArray *out[], int nargin, const mxArray out[1] = wrap_shared_ptr(pairResult.second,"Test", false); } -void Test_print_17(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_get_container_17(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + checkArguments("get_container",nargout,nargin-1,0); + auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); + out[0] = wrap_shared_ptr(boost::make_shared>(obj->get_container()),"std.vectorTest", false); +} + +void Test_print_18(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("print",nargout,nargin-1,0); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); obj->print(); } -void Test_return_Point2Ptr_18(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_Point2Ptr_19(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_Point2Ptr",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -315,7 +322,7 @@ void Test_return_Point2Ptr_18(int nargout, mxArray *out[], int nargin, const mxA } } -void Test_return_Test_19(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_Test_20(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_Test",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -323,7 +330,7 @@ void Test_return_Test_19(int nargout, mxArray *out[], int nargin, const mxArray out[0] = wrap_shared_ptr(boost::make_shared(obj->return_Test(value)),"Test", false); } -void Test_return_TestPtr_20(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_TestPtr_21(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_TestPtr",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -331,7 +338,7 @@ void Test_return_TestPtr_20(int nargout, mxArray *out[], int nargin, const mxArr out[0] = wrap_shared_ptr(obj->return_TestPtr(value),"Test", false); } -void Test_return_bool_21(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_bool_22(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_bool",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -339,7 +346,7 @@ void Test_return_bool_21(int nargout, mxArray *out[], int nargin, const mxArray out[0] = wrap< bool >(obj->return_bool(value)); } -void Test_return_double_22(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_double_23(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_double",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -347,7 +354,7 @@ void Test_return_double_22(int nargout, mxArray *out[], int nargin, const mxArra out[0] = wrap< double >(obj->return_double(value)); } -void Test_return_field_23(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_field_24(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_field",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -355,7 +362,7 @@ void Test_return_field_23(int nargout, mxArray *out[], int nargin, const mxArray out[0] = wrap< bool >(obj->return_field(t)); } -void Test_return_int_24(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_int_25(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_int",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -363,7 +370,7 @@ void Test_return_int_24(int nargout, mxArray *out[], int nargin, const mxArray * out[0] = wrap< int >(obj->return_int(value)); } -void Test_return_matrix1_25(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_matrix1_26(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_matrix1",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -371,7 +378,7 @@ void Test_return_matrix1_25(int nargout, mxArray *out[], int nargin, const mxArr out[0] = wrap< Matrix >(obj->return_matrix1(value)); } -void Test_return_matrix2_26(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_matrix2_27(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_matrix2",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -379,7 +386,7 @@ void Test_return_matrix2_26(int nargout, mxArray *out[], int nargin, const mxArr out[0] = wrap< Matrix >(obj->return_matrix2(value)); } -void Test_return_pair_27(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_pair_28(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_pair",nargout,nargin-1,2); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -390,7 +397,7 @@ void Test_return_pair_27(int nargout, mxArray *out[], int nargin, const mxArray out[1] = wrap< Matrix >(pairResult.second); } -void Test_return_pair_28(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_pair_29(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_pair",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -400,7 +407,7 @@ void Test_return_pair_28(int nargout, mxArray *out[], int nargin, const mxArray out[1] = wrap< Matrix >(pairResult.second); } -void Test_return_ptrs_29(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_ptrs_30(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_ptrs",nargout,nargin-1,2); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -411,7 +418,7 @@ void Test_return_ptrs_29(int nargout, mxArray *out[], int nargin, const mxArray out[1] = wrap_shared_ptr(pairResult.second,"Test", false); } -void Test_return_size_t_30(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_size_t_31(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_size_t",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -419,7 +426,7 @@ void Test_return_size_t_30(int nargout, mxArray *out[], int nargin, const mxArra out[0] = wrap< size_t >(obj->return_size_t(value)); } -void Test_return_string_31(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_string_32(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_string",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -427,7 +434,7 @@ void Test_return_string_31(int nargout, mxArray *out[], int nargin, const mxArra out[0] = wrap< string >(obj->return_string(value)); } -void Test_return_vector1_32(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_vector1_33(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_vector1",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -435,7 +442,7 @@ void Test_return_vector1_32(int nargout, mxArray *out[], int nargin, const mxArr out[0] = wrap< Vector >(obj->return_vector1(value)); } -void Test_return_vector2_33(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_return_vector2_34(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("return_vector2",nargout,nargin-1,1); auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); @@ -443,7 +450,31 @@ void Test_return_vector2_33(int nargout, mxArray *out[], int nargin, const mxArr out[0] = wrap< Vector >(obj->return_vector2(value)); } -void PrimitiveRefDouble_collectorInsertAndMakeBase_34(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void Test_set_container_35(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + checkArguments("set_container",nargout,nargin-1,1); + auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); + boost::shared_ptr> container = unwrap_shared_ptr< std::vector >(in[1], "ptr_stdvectorTest"); + obj->set_container(*container); +} + +void Test_set_container_36(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + checkArguments("set_container",nargout,nargin-1,1); + auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); + boost::shared_ptr> container = unwrap_shared_ptr< std::vector >(in[1], "ptr_stdvectorTest"); + obj->set_container(*container); +} + +void Test_set_container_37(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + checkArguments("set_container",nargout,nargin-1,1); + auto obj = unwrap_shared_ptr(in[0], "ptr_Test"); + boost::shared_ptr> container = unwrap_shared_ptr< std::vector >(in[1], "ptr_stdvectorTest"); + obj->set_container(*container); +} + +void PrimitiveRefDouble_collectorInsertAndMakeBase_38(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -452,7 +483,7 @@ void PrimitiveRefDouble_collectorInsertAndMakeBase_34(int nargout, mxArray *out[ collector_PrimitiveRefDouble.insert(self); } -void PrimitiveRefDouble_constructor_35(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void PrimitiveRefDouble_constructor_39(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -463,7 +494,7 @@ void PrimitiveRefDouble_constructor_35(int nargout, mxArray *out[], int nargin, *reinterpret_cast (mxGetData(out[0])) = self; } -void PrimitiveRefDouble_deconstructor_36(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void PrimitiveRefDouble_deconstructor_40(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { typedef boost::shared_ptr> Shared; checkArguments("delete_PrimitiveRefDouble",nargout,nargin,1); @@ -476,14 +507,14 @@ void PrimitiveRefDouble_deconstructor_36(int nargout, mxArray *out[], int nargin } } -void PrimitiveRefDouble_Brutal_37(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void PrimitiveRefDouble_Brutal_41(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { checkArguments("PrimitiveRefDouble.Brutal",nargout,nargin,1); double t = unwrap< double >(in[0]); out[0] = wrap_shared_ptr(boost::make_shared>(PrimitiveRef::Brutal(t)),"PrimitiveRefdouble", false); } -void MyVector3_collectorInsertAndMakeBase_38(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MyVector3_collectorInsertAndMakeBase_42(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -492,7 +523,7 @@ void MyVector3_collectorInsertAndMakeBase_38(int nargout, mxArray *out[], int na collector_MyVector3.insert(self); } -void MyVector3_constructor_39(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MyVector3_constructor_43(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -503,7 +534,7 @@ void MyVector3_constructor_39(int nargout, mxArray *out[], int nargin, const mxA *reinterpret_cast (mxGetData(out[0])) = self; } -void MyVector3_deconstructor_40(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MyVector3_deconstructor_44(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { typedef boost::shared_ptr> Shared; checkArguments("delete_MyVector3",nargout,nargin,1); @@ -516,7 +547,7 @@ void MyVector3_deconstructor_40(int nargout, mxArray *out[], int nargin, const m } } -void MyVector12_collectorInsertAndMakeBase_41(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MyVector12_collectorInsertAndMakeBase_45(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -525,7 +556,7 @@ void MyVector12_collectorInsertAndMakeBase_41(int nargout, mxArray *out[], int n collector_MyVector12.insert(self); } -void MyVector12_constructor_42(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MyVector12_constructor_46(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -536,7 +567,7 @@ void MyVector12_constructor_42(int nargout, mxArray *out[], int nargin, const mx *reinterpret_cast (mxGetData(out[0])) = self; } -void MyVector12_deconstructor_43(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MyVector12_deconstructor_47(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { typedef boost::shared_ptr> Shared; checkArguments("delete_MyVector12",nargout,nargin,1); @@ -549,7 +580,7 @@ void MyVector12_deconstructor_43(int nargout, mxArray *out[], int nargin, const } } -void MultipleTemplatesIntDouble_collectorInsertAndMakeBase_44(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MultipleTemplatesIntDouble_collectorInsertAndMakeBase_48(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -558,7 +589,7 @@ void MultipleTemplatesIntDouble_collectorInsertAndMakeBase_44(int nargout, mxArr collector_MultipleTemplatesIntDouble.insert(self); } -void MultipleTemplatesIntDouble_deconstructor_45(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MultipleTemplatesIntDouble_deconstructor_49(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { typedef boost::shared_ptr> Shared; checkArguments("delete_MultipleTemplatesIntDouble",nargout,nargin,1); @@ -571,7 +602,7 @@ void MultipleTemplatesIntDouble_deconstructor_45(int nargout, mxArray *out[], in } } -void MultipleTemplatesIntFloat_collectorInsertAndMakeBase_46(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MultipleTemplatesIntFloat_collectorInsertAndMakeBase_50(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -580,7 +611,7 @@ void MultipleTemplatesIntFloat_collectorInsertAndMakeBase_46(int nargout, mxArra collector_MultipleTemplatesIntFloat.insert(self); } -void MultipleTemplatesIntFloat_deconstructor_47(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MultipleTemplatesIntFloat_deconstructor_51(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { typedef boost::shared_ptr> Shared; checkArguments("delete_MultipleTemplatesIntFloat",nargout,nargin,1); @@ -593,7 +624,7 @@ void MultipleTemplatesIntFloat_deconstructor_47(int nargout, mxArray *out[], int } } -void MyFactorPosePoint2_collectorInsertAndMakeBase_48(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MyFactorPosePoint2_collectorInsertAndMakeBase_52(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -602,7 +633,7 @@ void MyFactorPosePoint2_collectorInsertAndMakeBase_48(int nargout, mxArray *out[ collector_MyFactorPosePoint2.insert(self); } -void MyFactorPosePoint2_constructor_49(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MyFactorPosePoint2_constructor_53(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -617,7 +648,7 @@ void MyFactorPosePoint2_constructor_49(int nargout, mxArray *out[], int nargin, *reinterpret_cast (mxGetData(out[0])) = self; } -void MyFactorPosePoint2_deconstructor_50(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void MyFactorPosePoint2_deconstructor_54(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { typedef boost::shared_ptr> Shared; checkArguments("delete_MyFactorPosePoint2",nargout,nargin,1); @@ -694,106 +725,118 @@ void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[]) Test_create_ptrs_16(nargout, out, nargin-1, in+1); break; case 17: - Test_print_17(nargout, out, nargin-1, in+1); + Test_get_container_17(nargout, out, nargin-1, in+1); break; case 18: - Test_return_Point2Ptr_18(nargout, out, nargin-1, in+1); + Test_print_18(nargout, out, nargin-1, in+1); break; case 19: - Test_return_Test_19(nargout, out, nargin-1, in+1); + Test_return_Point2Ptr_19(nargout, out, nargin-1, in+1); break; case 20: - Test_return_TestPtr_20(nargout, out, nargin-1, in+1); + Test_return_Test_20(nargout, out, nargin-1, in+1); break; case 21: - Test_return_bool_21(nargout, out, nargin-1, in+1); + Test_return_TestPtr_21(nargout, out, nargin-1, in+1); break; case 22: - Test_return_double_22(nargout, out, nargin-1, in+1); + Test_return_bool_22(nargout, out, nargin-1, in+1); break; case 23: - Test_return_field_23(nargout, out, nargin-1, in+1); + Test_return_double_23(nargout, out, nargin-1, in+1); break; case 24: - Test_return_int_24(nargout, out, nargin-1, in+1); + Test_return_field_24(nargout, out, nargin-1, in+1); break; case 25: - Test_return_matrix1_25(nargout, out, nargin-1, in+1); + Test_return_int_25(nargout, out, nargin-1, in+1); break; case 26: - Test_return_matrix2_26(nargout, out, nargin-1, in+1); + Test_return_matrix1_26(nargout, out, nargin-1, in+1); break; case 27: - Test_return_pair_27(nargout, out, nargin-1, in+1); + Test_return_matrix2_27(nargout, out, nargin-1, in+1); break; case 28: Test_return_pair_28(nargout, out, nargin-1, in+1); break; case 29: - Test_return_ptrs_29(nargout, out, nargin-1, in+1); + Test_return_pair_29(nargout, out, nargin-1, in+1); break; case 30: - Test_return_size_t_30(nargout, out, nargin-1, in+1); + Test_return_ptrs_30(nargout, out, nargin-1, in+1); break; case 31: - Test_return_string_31(nargout, out, nargin-1, in+1); + Test_return_size_t_31(nargout, out, nargin-1, in+1); break; case 32: - Test_return_vector1_32(nargout, out, nargin-1, in+1); + Test_return_string_32(nargout, out, nargin-1, in+1); break; case 33: - Test_return_vector2_33(nargout, out, nargin-1, in+1); + Test_return_vector1_33(nargout, out, nargin-1, in+1); break; case 34: - PrimitiveRefDouble_collectorInsertAndMakeBase_34(nargout, out, nargin-1, in+1); + Test_return_vector2_34(nargout, out, nargin-1, in+1); break; case 35: - PrimitiveRefDouble_constructor_35(nargout, out, nargin-1, in+1); + Test_set_container_35(nargout, out, nargin-1, in+1); break; case 36: - PrimitiveRefDouble_deconstructor_36(nargout, out, nargin-1, in+1); + Test_set_container_36(nargout, out, nargin-1, in+1); break; case 37: - PrimitiveRefDouble_Brutal_37(nargout, out, nargin-1, in+1); + Test_set_container_37(nargout, out, nargin-1, in+1); break; case 38: - MyVector3_collectorInsertAndMakeBase_38(nargout, out, nargin-1, in+1); + PrimitiveRefDouble_collectorInsertAndMakeBase_38(nargout, out, nargin-1, in+1); break; case 39: - MyVector3_constructor_39(nargout, out, nargin-1, in+1); + PrimitiveRefDouble_constructor_39(nargout, out, nargin-1, in+1); break; case 40: - MyVector3_deconstructor_40(nargout, out, nargin-1, in+1); + PrimitiveRefDouble_deconstructor_40(nargout, out, nargin-1, in+1); break; case 41: - MyVector12_collectorInsertAndMakeBase_41(nargout, out, nargin-1, in+1); + PrimitiveRefDouble_Brutal_41(nargout, out, nargin-1, in+1); break; case 42: - MyVector12_constructor_42(nargout, out, nargin-1, in+1); + MyVector3_collectorInsertAndMakeBase_42(nargout, out, nargin-1, in+1); break; case 43: - MyVector12_deconstructor_43(nargout, out, nargin-1, in+1); + MyVector3_constructor_43(nargout, out, nargin-1, in+1); break; case 44: - MultipleTemplatesIntDouble_collectorInsertAndMakeBase_44(nargout, out, nargin-1, in+1); + MyVector3_deconstructor_44(nargout, out, nargin-1, in+1); break; case 45: - MultipleTemplatesIntDouble_deconstructor_45(nargout, out, nargin-1, in+1); + MyVector12_collectorInsertAndMakeBase_45(nargout, out, nargin-1, in+1); break; case 46: - MultipleTemplatesIntFloat_collectorInsertAndMakeBase_46(nargout, out, nargin-1, in+1); + MyVector12_constructor_46(nargout, out, nargin-1, in+1); break; case 47: - MultipleTemplatesIntFloat_deconstructor_47(nargout, out, nargin-1, in+1); + MyVector12_deconstructor_47(nargout, out, nargin-1, in+1); break; case 48: - MyFactorPosePoint2_collectorInsertAndMakeBase_48(nargout, out, nargin-1, in+1); + MultipleTemplatesIntDouble_collectorInsertAndMakeBase_48(nargout, out, nargin-1, in+1); break; case 49: - MyFactorPosePoint2_constructor_49(nargout, out, nargin-1, in+1); + MultipleTemplatesIntDouble_deconstructor_49(nargout, out, nargin-1, in+1); break; case 50: - MyFactorPosePoint2_deconstructor_50(nargout, out, nargin-1, in+1); + MultipleTemplatesIntFloat_collectorInsertAndMakeBase_50(nargout, out, nargin-1, in+1); + break; + case 51: + MultipleTemplatesIntFloat_deconstructor_51(nargout, out, nargin-1, in+1); + break; + case 52: + MyFactorPosePoint2_collectorInsertAndMakeBase_52(nargout, out, nargin-1, in+1); + break; + case 53: + MyFactorPosePoint2_constructor_53(nargout, out, nargin-1, in+1); + break; + case 54: + MyFactorPosePoint2_deconstructor_54(nargout, out, nargin-1, in+1); break; } } catch(const std::exception& e) { diff --git a/tests/expected/matlab/special_cases_wrapper.cpp b/tests/expected/matlab/special_cases_wrapper.cpp index f1c03e9a1..b0ee1bcf8 100644 --- a/tests/expected/matlab/special_cases_wrapper.cpp +++ b/tests/expected/matlab/special_cases_wrapper.cpp @@ -25,6 +25,7 @@ typedef MyFactor MyFactorPosePoint2; typedef MyTemplate MyTemplatePoint2; typedef MyTemplate MyTemplateMatrix; typedef gtsam::PinholeCamera PinholeCameraCal3Bundler; +typedef gtsam::GeneralSFMFactor, gtsam::Point3> GeneralSFMFactorCal3Bundler; BOOST_CLASS_EXPORT_GUID(gtsam::Point2, "gtsamPoint2"); BOOST_CLASS_EXPORT_GUID(gtsam::Point3, "gtsamPoint3"); @@ -71,8 +72,12 @@ typedef std::set*> Collector_ClassD; static Collector_ClassD collector_ClassD; typedef std::set*> Collector_gtsamNonlinearFactorGraph; static Collector_gtsamNonlinearFactorGraph collector_gtsamNonlinearFactorGraph; +typedef std::set*> Collector_gtsamSfmTrack; +static Collector_gtsamSfmTrack collector_gtsamSfmTrack; typedef std::set*> Collector_gtsamPinholeCameraCal3Bundler; static Collector_gtsamPinholeCameraCal3Bundler collector_gtsamPinholeCameraCal3Bundler; +typedef std::set*> Collector_gtsamGeneralSFMFactorCal3Bundler; +static Collector_gtsamGeneralSFMFactorCal3Bundler collector_gtsamGeneralSFMFactorCal3Bundler; void _deleteAllObjects() { @@ -206,12 +211,24 @@ void _deleteAllObjects() collector_gtsamNonlinearFactorGraph.erase(iter++); anyDeleted = true; } } + { for(Collector_gtsamSfmTrack::iterator iter = collector_gtsamSfmTrack.begin(); + iter != collector_gtsamSfmTrack.end(); ) { + delete *iter; + collector_gtsamSfmTrack.erase(iter++); + anyDeleted = true; + } } { for(Collector_gtsamPinholeCameraCal3Bundler::iterator iter = collector_gtsamPinholeCameraCal3Bundler.begin(); iter != collector_gtsamPinholeCameraCal3Bundler.end(); ) { delete *iter; collector_gtsamPinholeCameraCal3Bundler.erase(iter++); anyDeleted = true; } } + { for(Collector_gtsamGeneralSFMFactorCal3Bundler::iterator iter = collector_gtsamGeneralSFMFactorCal3Bundler.begin(); + iter != collector_gtsamGeneralSFMFactorCal3Bundler.end(); ) { + delete *iter; + collector_gtsamGeneralSFMFactorCal3Bundler.erase(iter++); + anyDeleted = true; + } } if(anyDeleted) cout << "WARNING: Wrap modules with variables in the workspace have been reloaded due to\n" @@ -282,7 +299,29 @@ void gtsamNonlinearFactorGraph_addPrior_2(int nargout, mxArray *out[], int nargi obj->addPrior>(key,prior,noiseModel); } -void gtsamPinholeCameraCal3Bundler_collectorInsertAndMakeBase_3(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void gtsamSfmTrack_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_gtsamSfmTrack.insert(self); +} + +void gtsamSfmTrack_deconstructor_4(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + typedef boost::shared_ptr Shared; + checkArguments("delete_gtsamSfmTrack",nargout,nargin,1); + Shared *self = *reinterpret_cast(mxGetData(in[0])); + Collector_gtsamSfmTrack::iterator item; + item = collector_gtsamSfmTrack.find(self); + if(item != collector_gtsamSfmTrack.end()) { + delete self; + collector_gtsamSfmTrack.erase(item); + } +} + +void gtsamPinholeCameraCal3Bundler_collectorInsertAndMakeBase_5(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { mexAtExit(&_deleteAllObjects); typedef boost::shared_ptr> Shared; @@ -291,7 +330,7 @@ void gtsamPinholeCameraCal3Bundler_collectorInsertAndMakeBase_3(int nargout, mxA collector_gtsamPinholeCameraCal3Bundler.insert(self); } -void gtsamPinholeCameraCal3Bundler_deconstructor_4(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +void gtsamPinholeCameraCal3Bundler_deconstructor_6(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { typedef boost::shared_ptr> Shared; checkArguments("delete_gtsamPinholeCameraCal3Bundler",nargout,nargin,1); @@ -304,6 +343,28 @@ void gtsamPinholeCameraCal3Bundler_deconstructor_4(int nargout, mxArray *out[], } } +void gtsamGeneralSFMFactorCal3Bundler_collectorInsertAndMakeBase_7(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + mexAtExit(&_deleteAllObjects); + typedef boost::shared_ptr, gtsam::Point3>> Shared; + + Shared *self = *reinterpret_cast (mxGetData(in[0])); + collector_gtsamGeneralSFMFactorCal3Bundler.insert(self); +} + +void gtsamGeneralSFMFactorCal3Bundler_deconstructor_8(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + typedef boost::shared_ptr, gtsam::Point3>> Shared; + checkArguments("delete_gtsamGeneralSFMFactorCal3Bundler",nargout,nargin,1); + Shared *self = *reinterpret_cast(mxGetData(in[0])); + Collector_gtsamGeneralSFMFactorCal3Bundler::iterator item; + item = collector_gtsamGeneralSFMFactorCal3Bundler.find(self); + if(item != collector_gtsamGeneralSFMFactorCal3Bundler.end()) { + delete self; + collector_gtsamGeneralSFMFactorCal3Bundler.erase(item); + } +} + void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[]) { @@ -326,10 +387,22 @@ void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[]) gtsamNonlinearFactorGraph_addPrior_2(nargout, out, nargin-1, in+1); break; case 3: - gtsamPinholeCameraCal3Bundler_collectorInsertAndMakeBase_3(nargout, out, nargin-1, in+1); + gtsamSfmTrack_collectorInsertAndMakeBase_3(nargout, out, nargin-1, in+1); break; case 4: - gtsamPinholeCameraCal3Bundler_deconstructor_4(nargout, out, nargin-1, in+1); + gtsamSfmTrack_deconstructor_4(nargout, out, nargin-1, in+1); + break; + case 5: + gtsamPinholeCameraCal3Bundler_collectorInsertAndMakeBase_5(nargout, out, nargin-1, in+1); + break; + case 6: + gtsamPinholeCameraCal3Bundler_deconstructor_6(nargout, out, nargin-1, in+1); + break; + case 7: + gtsamGeneralSFMFactorCal3Bundler_collectorInsertAndMakeBase_7(nargout, out, nargin-1, in+1); + break; + case 8: + gtsamGeneralSFMFactorCal3Bundler_deconstructor_8(nargout, out, nargin-1, in+1); break; } } catch(const std::exception& e) { diff --git a/tests/expected/python/class_pybind.cpp b/tests/expected/python/class_pybind.cpp index a996f35ae..68f7a42e4 100644 --- a/tests/expected/python/class_pybind.cpp +++ b/tests/expected/python/class_pybind.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "gtsam/nonlinear/utilities.h" // for RedirectCout. #include "folder/path/to/Test.h" @@ -48,12 +49,12 @@ PYBIND11_MODULE(class_py, m_) { .def("return_matrix2",[](Test* self, const gtsam::Matrix& value){return self->return_matrix2(value);}, py::arg("value")) .def("arg_EigenConstRef",[](Test* self, const gtsam::Matrix& value){ self->arg_EigenConstRef(value);}, py::arg("value")) .def("return_field",[](Test* self, const Test& t){return self->return_field(t);}, py::arg("t")) - .def("return_TestPtr",[](Test* self, const std::shared_ptr& value){return self->return_TestPtr(value);}, py::arg("value")) - .def("return_Test",[](Test* self, std::shared_ptr& value){return self->return_Test(value);}, py::arg("value")) + .def("return_TestPtr",[](Test* self, const std::shared_ptr value){return self->return_TestPtr(value);}, py::arg("value")) + .def("return_Test",[](Test* self, std::shared_ptr value){return self->return_Test(value);}, py::arg("value")) .def("return_Point2Ptr",[](Test* self, bool value){return self->return_Point2Ptr(value);}, py::arg("value")) .def("create_ptrs",[](Test* self){return self->create_ptrs();}) .def("create_MixedPtrs",[](Test* self){return self->create_MixedPtrs();}) - .def("return_ptrs",[](Test* self, std::shared_ptr& p1, std::shared_ptr& p2){return self->return_ptrs(p1, p2);}, py::arg("p1"), py::arg("p2")) + .def("return_ptrs",[](Test* self, std::shared_ptr p1, std::shared_ptr p2){return self->return_ptrs(p1, p2);}, py::arg("p1"), py::arg("p2")) .def("print_",[](Test* self){ self->print();}) .def("__repr__", [](const Test &a) { @@ -61,6 +62,10 @@ PYBIND11_MODULE(class_py, m_) { a.print(); return redirect.str(); }) + .def("set_container",[](Test* self, std::vector container){ self->set_container(container);}, py::arg("container")) + .def("set_container",[](Test* self, std::vector> container){ self->set_container(container);}, py::arg("container")) + .def("set_container",[](Test* self, std::vector container){ self->set_container(container);}, py::arg("container")) + .def("get_container",[](Test* self){return self->get_container();}) .def_readwrite("model_ptr", &Test::model_ptr); py::class_, std::shared_ptr>>(m_, "PrimitiveRefDouble") @@ -78,7 +83,7 @@ PYBIND11_MODULE(class_py, m_) { py::class_, std::shared_ptr>>(m_, "MultipleTemplatesIntFloat"); py::class_, std::shared_ptr>>(m_, "MyFactorPosePoint2") - .def(py::init&>(), py::arg("key1"), py::arg("key2"), py::arg("measured"), py::arg("noiseModel")); + .def(py::init>(), py::arg("key1"), py::arg("key2"), py::arg("measured"), py::arg("noiseModel")); #include "python/specializations.h" diff --git a/tests/expected/python/functions_pybind.cpp b/tests/expected/python/functions_pybind.cpp index ac78563b9..a657bee67 100644 --- a/tests/expected/python/functions_pybind.cpp +++ b/tests/expected/python/functions_pybind.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "gtsam/nonlinear/utilities.h" // for RedirectCout. @@ -21,8 +22,8 @@ PYBIND11_MODULE(functions_py, m_) { m_.doc() = "pybind11 wrapper of functions_py"; - m_.def("load2D",[](string filename, std::shared_ptr& 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& 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, std::shared_ptr 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 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("aGlobalFunction",[](){return ::aGlobalFunction();}); m_.def("overloadedGlobalFunction",[](int a){return ::overloadedGlobalFunction(a);}, py::arg("a")); diff --git a/tests/expected/python/geometry_pybind.cpp b/tests/expected/python/geometry_pybind.cpp index 22a838215..64ba5485d 100644 --- a/tests/expected/python/geometry_pybind.cpp +++ b/tests/expected/python/geometry_pybind.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "gtsam/nonlinear/utilities.h" // for RedirectCout. #include "gtsam/geometry/Point2.h" @@ -34,10 +35,10 @@ PYBIND11_MODULE(geometry_py, m_) { .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& a){ self->argChar(a);}, py::arg("a")) + .def("argChar",[](gtsam::Point2* self, std::shared_ptr 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& a){ self->argChar(a);}, py::arg("a")) + .def("argChar",[](gtsam::Point2* self, const std::shared_ptr 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")) diff --git a/tests/expected/python/inheritance_pybind.cpp b/tests/expected/python/inheritance_pybind.cpp index b349df706..6f34d39b6 100644 --- a/tests/expected/python/inheritance_pybind.cpp +++ b/tests/expected/python/inheritance_pybind.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "gtsam/nonlinear/utilities.h" // for RedirectCout. @@ -30,12 +31,12 @@ PYBIND11_MODULE(inheritance_py, m_) { .def("templatedMethodVector",[](MyTemplate* self, const gtsam::Vector& t){return self->templatedMethod(t);}, py::arg("t")) .def("templatedMethodMatrix",[](MyTemplate* self, const gtsam::Matrix& t){return self->templatedMethod(t);}, py::arg("t")) .def("accept_T",[](MyTemplate* self, const gtsam::Point2& value){ self->accept_T(value);}, py::arg("value")) - .def("accept_Tptr",[](MyTemplate* self, std::shared_ptr& value){ self->accept_Tptr(value);}, py::arg("value")) - .def("return_Tptr",[](MyTemplate* self, std::shared_ptr& value){return self->return_Tptr(value);}, py::arg("value")) + .def("accept_Tptr",[](MyTemplate* self, std::shared_ptr value){ self->accept_Tptr(value);}, py::arg("value")) + .def("return_Tptr",[](MyTemplate* self, std::shared_ptr value){return self->return_Tptr(value);}, py::arg("value")) .def("return_T",[](MyTemplate* self, gtsam::Point2* value){return self->return_T(value);}, py::arg("value")) .def("create_ptrs",[](MyTemplate* self){return self->create_ptrs();}) .def("create_MixedPtrs",[](MyTemplate* self){return self->create_MixedPtrs();}) - .def("return_ptrs",[](MyTemplate* self, std::shared_ptr& p1, std::shared_ptr& p2){return self->return_ptrs(p1, p2);}, py::arg("p1"), py::arg("p2")) + .def("return_ptrs",[](MyTemplate* self, std::shared_ptr p1, std::shared_ptr p2){return self->return_ptrs(p1, p2);}, py::arg("p1"), py::arg("p2")) .def_static("Level",[](const gtsam::Point2& K){return MyTemplate::Level(K);}, py::arg("K")); py::class_, MyBase, std::shared_ptr>>(m_, "MyTemplateMatrix") @@ -45,12 +46,12 @@ PYBIND11_MODULE(inheritance_py, m_) { .def("templatedMethodVector",[](MyTemplate* self, const gtsam::Vector& t){return self->templatedMethod(t);}, py::arg("t")) .def("templatedMethodMatrix",[](MyTemplate* self, const gtsam::Matrix& t){return self->templatedMethod(t);}, py::arg("t")) .def("accept_T",[](MyTemplate* self, const gtsam::Matrix& value){ self->accept_T(value);}, py::arg("value")) - .def("accept_Tptr",[](MyTemplate* self, const std::shared_ptr& value){ self->accept_Tptr(value);}, py::arg("value")) - .def("return_Tptr",[](MyTemplate* self, const std::shared_ptr& value){return self->return_Tptr(value);}, py::arg("value")) + .def("accept_Tptr",[](MyTemplate* self, const std::shared_ptr value){ self->accept_Tptr(value);}, py::arg("value")) + .def("return_Tptr",[](MyTemplate* self, const std::shared_ptr value){return self->return_Tptr(value);}, py::arg("value")) .def("return_T",[](MyTemplate* self, const gtsam::Matrix* value){return self->return_T(value);}, py::arg("value")) .def("create_ptrs",[](MyTemplate* self){return self->create_ptrs();}) .def("create_MixedPtrs",[](MyTemplate* self){return self->create_MixedPtrs();}) - .def("return_ptrs",[](MyTemplate* self, const std::shared_ptr& p1, const std::shared_ptr& p2){return self->return_ptrs(p1, p2);}, py::arg("p1"), py::arg("p2")) + .def("return_ptrs",[](MyTemplate* self, const std::shared_ptr p1, const std::shared_ptr p2){return self->return_ptrs(p1, p2);}, py::arg("p1"), py::arg("p2")) .def_static("Level",[](const gtsam::Matrix& K){return MyTemplate::Level(K);}, py::arg("K")); diff --git a/tests/expected/python/namespaces_pybind.cpp b/tests/expected/python/namespaces_pybind.cpp index ee2f41c5d..e0e21d93b 100644 --- a/tests/expected/python/namespaces_pybind.cpp +++ b/tests/expected/python/namespaces_pybind.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "gtsam/nonlinear/utilities.h" // for RedirectCout. #include "path/to/ns1.h" diff --git a/tests/expected/python/operator_pybind.cpp b/tests/expected/python/operator_pybind.cpp new file mode 100644 index 000000000..536d4f7da --- /dev/null +++ b/tests/expected/python/operator_pybind.cpp @@ -0,0 +1,40 @@ + + +#include +#include +#include +#include +#include "gtsam/nonlinear/utilities.h" // for RedirectCout. + +#include "gtsam/geometry/Pose3.h" + +#include "wrap/serialization.h" +#include + + + + + +using namespace std; + +namespace py = pybind11; + +PYBIND11_MODULE(operator_py, m_) { + m_.doc() = "pybind11 wrapper of operator_py"; + + pybind11::module m_gtsam = m_.def_submodule("gtsam", "gtsam submodule"); + + py::class_>(m_gtsam, "Pose3") + .def(py::init<>()) + .def(py::init(), py::arg("R"), py::arg("t")) + .def(py::self * py::self); + + py::class_, std::shared_ptr>>(m_gtsam, "ContainerMatrix") + .def("__call__", >sam::Container::operator()) + .def("__getitem__", >sam::Container::operator[]); + + +#include "python/specializations.h" + +} + diff --git a/tests/expected/python/special_cases_pybind.cpp b/tests/expected/python/special_cases_pybind.cpp index fb15a004d..d436cdb06 100644 --- a/tests/expected/python/special_cases_pybind.cpp +++ b/tests/expected/python/special_cases_pybind.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "gtsam/nonlinear/utilities.h" // for RedirectCout. #include "gtsam/geometry/Cal3Bundler.h" @@ -24,10 +25,15 @@ PYBIND11_MODULE(special_cases_py, m_) { 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")); + .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_>(m_gtsam, "SfmTrack") + .def_readwrite("measurements", >sam::SfmTrack::measurements); py::class_, std::shared_ptr>>(m_gtsam, "PinholeCameraCal3Bundler"); + py::class_, gtsam::Point3>, std::shared_ptr, gtsam::Point3>>>(m_gtsam, "GeneralSFMFactorCal3Bundler"); + #include "python/specializations.h" diff --git a/tests/fixtures/class.i b/tests/fixtures/class.i index 1e2fce338..f4683a032 100644 --- a/tests/fixtures/class.i +++ b/tests/fixtures/class.i @@ -63,6 +63,11 @@ class Test { void print() const; + void set_container(std::vector container); + void set_container(std::vector container); + void set_container(std::vector container); + std::vector get_container() const; + // comments at the end! // even more comments at the end! diff --git a/tests/fixtures/operator.i b/tests/fixtures/operator.i new file mode 100644 index 000000000..817244e3e --- /dev/null +++ b/tests/fixtures/operator.i @@ -0,0 +1,16 @@ +namespace gtsam { + +#include +class Pose3 { + Pose3(); + Pose3(gtsam::Rot3 R, gtsam::Point3 t); + + gtsam::Pose3 operator*(gtsam::Pose3 other) const; +}; + +template +class Container { + gtsam::JacobianFactor operator()(const T& m) const; + T operator[](size_t idx) const; +}; +} diff --git a/tests/fixtures/special_cases.i b/tests/fixtures/special_cases.i index 9451eed24..da1170c5c 100644 --- a/tests/fixtures/special_cases.i +++ b/tests/fixtures/special_cases.i @@ -10,8 +10,19 @@ class PinholeCamera {}; typedef gtsam::PinholeCamera PinholeCameraCal3Bundler; class NonlinearFactorGraph { - template}> - void addPrior(size_t key, const T& prior, const gtsam::noiseModel::Base* noiseModel); + template }> + void addPrior(size_t key, const T& prior, + const gtsam::noiseModel::Base* noiseModel); }; -} \ No newline at end of file +// Typedef with template as template arg. +template +class GeneralSFMFactor {}; +typedef gtsam::GeneralSFMFactor, gtsam::Point3> GeneralSFMFactorCal3Bundler; + +// Template as template arg for class property. +class SfmTrack { + std::vector> measurements; +}; + +} // namespace gtsam diff --git a/tests/pybind_wrapper.tpl b/tests/pybind_wrapper.tpl index 836075edf..b23f5bee7 100644 --- a/tests/pybind_wrapper.tpl +++ b/tests/pybind_wrapper.tpl @@ -3,6 +3,7 @@ #include #include #include +#include #include "gtsam/nonlinear/utilities.h" // for RedirectCout. {includes} diff --git a/tests/test_interface_parser.py b/tests/test_interface_parser.py index fad846365..23f931fdd 100644 --- a/tests/test_interface_parser.py +++ b/tests/test_interface_parser.py @@ -21,7 +21,8 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from gtwrap.interface_parser import (ArgumentList, Class, Constructor, ForwardDeclaration, GlobalFunction, Include, Method, Module, Namespace, - ReturnType, StaticMethod, Type, + Operator, ReturnType, StaticMethod, + TemplatedType, Type, TypedefTemplateInstantiation, Typename) @@ -32,28 +33,104 @@ class TestInterfaceParser(unittest.TestCase): typename = Typename.rule.parseString("size_t")[0] self.assertEqual("size_t", typename.name) - typename = Typename.rule.parseString( - "gtsam::PinholeCamera")[0] - self.assertEqual("PinholeCamera", typename.name) - self.assertEqual(["gtsam"], typename.namespaces) - self.assertEqual("Cal3S2", typename.instantiations[0].name) - self.assertEqual(["gtsam"], typename.instantiations[0].namespaces) - - def test_type(self): - """Test for Type.""" + def test_basic_type(self): + """Tests for BasicType.""" + # Check basis type t = Type.rule.parseString("int x")[0] self.assertEqual("int", t.typename.name) - self.assertTrue(t.is_basis) - - t = Type.rule.parseString("T x")[0] - self.assertEqual("T", t.typename.name) - self.assertTrue(not t.is_basis) + self.assertTrue(t.is_basic) + # Check const t = Type.rule.parseString("const int x")[0] self.assertEqual("int", t.typename.name) - self.assertTrue(t.is_basis) + self.assertTrue(t.is_basic) self.assertTrue(t.is_const) + # Check shared pointer + t = Type.rule.parseString("int* x")[0] + self.assertEqual("int", t.typename.name) + self.assertTrue(t.is_shared_ptr) + + # Check raw pointer + t = Type.rule.parseString("int@ x")[0] + self.assertEqual("int", t.typename.name) + self.assertTrue(t.is_ptr) + + # Check reference + t = Type.rule.parseString("int& x")[0] + self.assertEqual("int", t.typename.name) + self.assertTrue(t.is_ref) + + # Check const reference + t = Type.rule.parseString("const int& x")[0] + self.assertEqual("int", t.typename.name) + self.assertTrue(t.is_const) + self.assertTrue(t.is_ref) + + def test_custom_type(self): + """Tests for CustomType.""" + # Check qualified type + t = Type.rule.parseString("gtsam::Pose3 x")[0] + self.assertEqual("Pose3", t.typename.name) + self.assertEqual(["gtsam"], t.typename.namespaces) + self.assertTrue(not t.is_basic) + + # Check const + t = Type.rule.parseString("const gtsam::Pose3 x")[0] + self.assertEqual("Pose3", t.typename.name) + self.assertEqual(["gtsam"], t.typename.namespaces) + self.assertTrue(t.is_const) + + # Check shared pointer + t = Type.rule.parseString("gtsam::Pose3* x")[0] + self.assertEqual("Pose3", t.typename.name) + self.assertEqual(["gtsam"], t.typename.namespaces) + self.assertTrue(t.is_shared_ptr) + self.assertEqual("std::shared_ptr", + t.to_cpp(use_boost=False)) + self.assertEqual("boost::shared_ptr", + t.to_cpp(use_boost=True)) + + # Check raw pointer + t = Type.rule.parseString("gtsam::Pose3@ x")[0] + self.assertEqual("Pose3", t.typename.name) + self.assertEqual(["gtsam"], t.typename.namespaces) + self.assertTrue(t.is_ptr) + + # Check reference + t = Type.rule.parseString("gtsam::Pose3& x")[0] + self.assertEqual("Pose3", t.typename.name) + self.assertEqual(["gtsam"], t.typename.namespaces) + self.assertTrue(t.is_ref) + + # Check const reference + t = Type.rule.parseString("const gtsam::Pose3& x")[0] + self.assertEqual("Pose3", t.typename.name) + self.assertEqual(["gtsam"], t.typename.namespaces) + self.assertTrue(t.is_const) + self.assertTrue(t.is_ref) + + def test_templated_type(self): + """Test a templated type.""" + t = TemplatedType.rule.parseString("Eigen::Matrix")[0] + self.assertEqual("Matrix", t.typename.name) + self.assertEqual(["Eigen"], t.typename.namespaces) + self.assertEqual("double", t.typename.instantiations[0].name) + self.assertEqual("3", t.typename.instantiations[1].name) + self.assertEqual("4", t.typename.instantiations[2].name) + + t = TemplatedType.rule.parseString( + "gtsam::PinholeCamera")[0] + self.assertEqual("PinholeCamera", t.typename.name) + self.assertEqual(["gtsam"], t.typename.namespaces) + self.assertEqual("Cal3S2", t.typename.instantiations[0].name) + self.assertEqual(["gtsam"], t.typename.instantiations[0].namespaces) + + t = TemplatedType.rule.parseString("PinholeCamera")[0] + self.assertEqual("PinholeCamera", t.typename.name) + self.assertEqual("Cal3S2", t.typename.instantiations[0].name) + self.assertTrue(t.template_params[0].is_shared_ptr) + def test_empty_arguments(self): """Test no arguments.""" empty_args = ArgumentList.rule.parseString("")[0] @@ -89,28 +166,41 @@ class TestInterfaceParser(unittest.TestCase): self.assertTrue(args[6].ctype.is_ref and args[6].ctype.is_const) self.assertTrue(args[7].ctype.is_ptr and args[7].ctype.is_const) + def test_argument_list_templated(self): + """Test arguments list where the arguments can be templated.""" + arg_string = "std::pair steps, vector vector_of_pointers" + args = ArgumentList.rule.parseString(arg_string)[0] + args_list = args.args_list + self.assertEqual(2, len(args_list)) + self.assertEqual("std::pair", + args_list[0].ctype.to_cpp(False)) + self.assertEqual("vector>", + args_list[1].ctype.to_cpp(False)) + self.assertEqual("vector>", + args_list[1].ctype.to_cpp(True)) + def test_return_type(self): """Test ReturnType""" # Test void return_type = ReturnType.rule.parseString("void")[0] self.assertEqual("void", return_type.type1.typename.name) - self.assertTrue(return_type.type1.is_basis) + self.assertTrue(return_type.type1.is_basic) # Test basis type return_type = ReturnType.rule.parseString("size_t")[0] self.assertEqual("size_t", return_type.type1.typename.name) self.assertTrue(not return_type.type2) - self.assertTrue(return_type.type1.is_basis) + self.assertTrue(return_type.type1.is_basic) # Test with qualifiers return_type = ReturnType.rule.parseString("int&")[0] self.assertEqual("int", return_type.type1.typename.name) - self.assertTrue(return_type.type1.is_basis + self.assertTrue(return_type.type1.is_basic and return_type.type1.is_ref) return_type = ReturnType.rule.parseString("const int")[0] self.assertEqual("int", return_type.type1.typename.name) - self.assertTrue(return_type.type1.is_basis + self.assertTrue(return_type.type1.is_basic and return_type.type1.is_const) # Test pair return @@ -157,6 +247,32 @@ class TestInterfaceParser(unittest.TestCase): self.assertEqual("f", ret.name) self.assertEqual(3, len(ret.args)) + def test_operator_overload(self): + """Test for operator overloading.""" + # Unary operator + wrap_string = "gtsam::Vector2 operator-() const;" + ret = Operator.rule.parseString(wrap_string)[0] + self.assertEqual("operator", ret.name) + self.assertEqual("-", ret.operator) + self.assertEqual("Vector2", ret.return_type.type1.typename.name) + self.assertEqual("gtsam::Vector2", + ret.return_type.type1.typename.to_cpp()) + self.assertTrue(len(ret.args) == 0) + self.assertTrue(ret.is_unary) + + # Binary operator + wrap_string = "gtsam::Vector2 operator*(const gtsam::Vector2 &v) const;" + ret = Operator.rule.parseString(wrap_string)[0] + self.assertEqual("operator", ret.name) + self.assertEqual("*", ret.operator) + self.assertEqual("Vector2", ret.return_type.type1.typename.name) + self.assertEqual("gtsam::Vector2", + ret.return_type.type1.typename.to_cpp()) + self.assertTrue(len(ret.args) == 1) + self.assertEqual("const gtsam::Vector2 &", + repr(ret.args.args_list[0].ctype)) + self.assertTrue(not ret.is_unary) + def test_typedef_template_instantiation(self): """Test for typedef'd instantiation of a template.""" typedef = TypedefTemplateInstantiation.rule.parseString(""" @@ -283,7 +399,7 @@ class TestInterfaceParser(unittest.TestCase): fwd = ForwardDeclaration.rule.parseString( "virtual class Test:gtsam::Point3;")[0] - fwd_name = fwd.name.asList()[0] + fwd_name = fwd.name self.assertEqual("Test", fwd_name.name) self.assertTrue(fwd.is_virtual) diff --git a/tests/test_pybind_wrapper.py b/tests/test_pybind_wrapper.py index c5df5deb5..5eff55446 100644 --- a/tests/test_pybind_wrapper.py +++ b/tests/test_pybind_wrapper.py @@ -134,6 +134,18 @@ class TestWrap(unittest.TestCase): self.compare_and_diff('namespaces_pybind.cpp', output) + def test_operator_overload(self): + """ + Tests for operator overloading. + """ + with open(osp.join(self.INTERFACE_DIR, 'operator.i'), 'r') as f: + content = f.read() + + output = self.wrap_content(content, 'operator_py', + self.PYTHON_ACTUAL_DIR) + + self.compare_and_diff('operator_pybind.cpp', output) + def test_special_cases(self): """ Tests for some unique, non-trivial features.