Squashed 'wrap/' changes from 07330d100..d9ae5ce03

d9ae5ce03 Merge pull request #118 from borglab/feature/matlab-multi-files
9adddf7dd update the main script for matlab wrapping
0b0398d46 remove debug statements since they aren't needed for now
df064a364 support for parsing mutiple interface files for Matlab wrapping
1929e197c add test for parsing multiple interface files
bac442056 Merge pull request #117 from borglab/fix/matlab-refactor
331f4a8ce update tests to remove redundant code
5426e3af4 generate all content from within the wrap function
f78612bf9 make directory check common
b7acd7a1f fixed import and test setup
88007b153 Merge pull request #116 from borglab/feature/matlab-refactor
a074896e6 utils -> mixins
414557e00 structure
187100439 update gitignore
adbc55aea don't use class attributes in matlab wrapper
f45ba5b2d broke down some large functions into smaller ones
7756f0548 add mixin for checks and call method to wrap global functions
a318e2a67 Merge pull request #115 from borglab/feature/multiple-modules
b02b74c3d convert matlab_wrapper to a submodule
be8641e83 improved function naming in tests
02ddbfbb0 update tests and docs
dfbded2c7 small fixes
e9ec5af07 update docs
d124e2cfb wrap multiple files
7c7342f86 update cmake to take in new changes for multiple modules
54850f724 Merge pull request #114 from borglab/fix/remove-py35
71ee98321 add mypy annotations
ccaea6294 remove support for python 3.5

git-subtree-dir: wrap
git-subtree-split: d9ae5ce036c4315db3c28b12db9c73eae246f314
release/4.3a0
Varun Agrawal 2021-07-11 08:10:35 -07:00
parent 56bede07cd
commit 4c410fcd0e
41 changed files with 1419 additions and 1628 deletions

View File

@ -10,7 +10,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: [3.5, 3.6, 3.7, 3.8, 3.9] python-version: [3.6, 3.7, 3.8, 3.9]
steps: steps:
- name: Checkout - name: Checkout

View File

@ -10,7 +10,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: [3.5, 3.6, 3.7, 3.8, 3.9] python-version: [3.6, 3.7, 3.8, 3.9]
steps: steps:
- name: Checkout - name: Checkout

2
.gitignore vendored
View File

@ -8,4 +8,4 @@ __pycache__/
# Files related to code coverage stats # Files related to code coverage stats
**/.coverage **/.coverage
gtwrap/matlab_wrapper.tpl gtwrap/matlab_wrapper/matlab_wrapper.tpl

View File

@ -58,7 +58,7 @@ if(NOT DEFINED GTWRAP_INCLUDE_NAME)
endif() endif()
configure_file(${PROJECT_SOURCE_DIR}/templates/matlab_wrapper.tpl.in configure_file(${PROJECT_SOURCE_DIR}/templates/matlab_wrapper.tpl.in
${PROJECT_SOURCE_DIR}/gtwrap/matlab_wrapper.tpl) ${PROJECT_SOURCE_DIR}/gtwrap/matlab_wrapper/matlab_wrapper.tpl)
# Install the gtwrap python package as a directory so it can be found by CMake # Install the gtwrap python package as a directory so it can be found by CMake
# for wrapping. # for wrapping.

View File

@ -192,12 +192,14 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the
- **DO NOT** re-define an overriden function already declared in the external (forward-declared) base class. This will cause an ambiguity problem in the Pybind header file. - **DO NOT** re-define an overriden function already declared in the external (forward-declared) base class. This will cause an ambiguity problem in the Pybind header file.
- Splitting wrapper over multiple files
- The Pybind11 wrapper supports splitting the wrapping code over multiple files.
- To be able to use classes from another module, simply import the C++ header file in that wrapper file.
- Unfortunately, this means that aliases can no longer be used.
- Similarly, there can be multiple `preamble.h` and `specializations.h` files. Each of these should match the module file name.
### TODO ### TODO
- Default values for arguments.
- WORKAROUND: make multiple versions of the same function for different configurations of default arguments.
- Handle `gtsam::Rot3M` conversions to quaternions. - Handle `gtsam::Rot3M` conversions to quaternions.
- Parse return of const ref arguments. - Parse return of const ref arguments.
- Parse `std::string` variants and convert directly to special string. - Parse `std::string` variants and convert directly to special string.
- Add enum support.
- Add generalized serialization support via `boost.serialization` with hooks to MATLAB save/load. - Add generalized serialization support via `boost.serialization` with hooks to MATLAB save/load.

View File

@ -29,8 +29,10 @@ Using `wrap` in your project is straightforward from here. In your `CMakeLists.t
```cmake ```cmake
find_package(gtwrap) find_package(gtwrap)
set(interface_files ${PROJECT_SOURCE_DIR}/cpp/${PROJECT_NAME}.h)
pybind_wrap(${PROJECT_NAME}_py # target pybind_wrap(${PROJECT_NAME}_py # target
${PROJECT_SOURCE_DIR}/cpp/${PROJECT_NAME}.h # interface header file "${interface_files}" # list of interface header files
"${PROJECT_NAME}.cpp" # the generated cpp "${PROJECT_NAME}.cpp" # the generated cpp
"${PROJECT_NAME}" # module_name "${PROJECT_NAME}" # module_name
"${PROJECT_MODULE_NAME}" # top namespace in the cpp file e.g. gtsam "${PROJECT_MODULE_NAME}" # top namespace in the cpp file e.g. gtsam

View File

@ -13,15 +13,14 @@ gtwrap_get_python_version(${WRAP_PYTHON_VERSION})
message(STATUS "Setting Python version for wrapper") message(STATUS "Setting Python version for wrapper")
set(PYBIND11_PYTHON_VERSION ${WRAP_PYTHON_VERSION}) set(PYBIND11_PYTHON_VERSION ${WRAP_PYTHON_VERSION})
# User-friendly Pybind11 wrapping and installing function. # User-friendly Pybind11 wrapping and installing function. Builds a Pybind11
# Builds a Pybind11 module from the provided interface_header. # module from the provided interface_headers. For example, for the interface
# For example, for the interface header gtsam.h, this will # header gtsam.h, this will build the wrap module 'gtsam_py.cc'.
# build the wrap module 'gtsam_py.cc'.
# #
# Arguments: # Arguments:
# ~~~ # ~~~
# target: The Make target # target: The Make target
# interface_header: The relative path to the wrapper interface definition file. # interface_headers: List of paths to the wrapper interface definition files. The top level interface file should be first.
# generated_cpp: The name of the cpp file which is generated from the tpl file. # generated_cpp: The name of the cpp file which is generated from the tpl file.
# module_name: The name of the Python module to use. # module_name: The name of the Python module to use.
# top_namespace: The C++ namespace under which the code to be wrapped exists. # top_namespace: The C++ namespace under which the code to be wrapped exists.
@ -31,16 +30,17 @@ set(PYBIND11_PYTHON_VERSION ${WRAP_PYTHON_VERSION})
# libs: Libraries to link with. # libs: Libraries to link with.
# dependencies: Dependencies which need to be built before the wrapper. # dependencies: Dependencies which need to be built before the wrapper.
# use_boost (optional): Flag indicating whether to include Boost. # use_boost (optional): Flag indicating whether to include Boost.
function(pybind_wrap function(
target pybind_wrap
interface_header target
generated_cpp interface_headers
module_name generated_cpp
top_namespace module_name
ignore_classes top_namespace
module_template ignore_classes
libs module_template
dependencies) libs
dependencies)
set(ExtraMacroArgs ${ARGN}) set(ExtraMacroArgs ${ARGN})
list(GET ExtraMacroArgs 0 USE_BOOST) list(GET ExtraMacroArgs 0 USE_BOOST)
if(USE_BOOST) if(USE_BOOST)
@ -49,57 +49,62 @@ function(pybind_wrap
set(_WRAP_BOOST_ARG "") set(_WRAP_BOOST_ARG "")
endif(USE_BOOST) endif(USE_BOOST)
if (UNIX) if(UNIX)
set(GTWRAP_PATH_SEPARATOR ":") set(GTWRAP_PATH_SEPARATOR ":")
else() else()
set(GTWRAP_PATH_SEPARATOR ";") set(GTWRAP_PATH_SEPARATOR ";")
endif() endif()
add_custom_command(OUTPUT ${generated_cpp} # Convert .i file names to .cpp file names.
COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${GTWRAP_PACKAGE_DIR}${GTWRAP_PATH_SEPARATOR}$ENV{PYTHONPATH}" foreach(filepath ${interface_headers})
${PYTHON_EXECUTABLE} get_filename_component(interface ${filepath} NAME)
${PYBIND_WRAP_SCRIPT} string(REPLACE ".i" ".cpp" cpp_file ${interface})
--src list(APPEND cpp_files ${cpp_file})
${interface_header} endforeach()
--out
${generated_cpp} add_custom_command(
--module_name OUTPUT ${cpp_files}
${module_name} COMMAND
--top_module_namespaces ${CMAKE_COMMAND} -E env
"${top_namespace}" "PYTHONPATH=${GTWRAP_PACKAGE_DIR}${GTWRAP_PATH_SEPARATOR}$ENV{PYTHONPATH}"
--ignore ${PYTHON_EXECUTABLE} ${PYBIND_WRAP_SCRIPT} --src "${interface_headers}"
${ignore_classes} --out "${generated_cpp}" --module_name ${module_name}
--template --top_module_namespaces "${top_namespace}" --ignore ${ignore_classes}
${module_template} --template ${module_template} ${_WRAP_BOOST_ARG}
${_WRAP_BOOST_ARG} DEPENDS "${interface_headers}" ${module_template}
DEPENDS ${interface_header} ${module_template} VERBATIM)
VERBATIM)
add_custom_target(pybind_wrap_${module_name} ALL DEPENDS ${generated_cpp}) add_custom_target(pybind_wrap_${module_name} ALL DEPENDS ${cpp_files})
# Late dependency injection, to make sure this gets called whenever the # Late dependency injection, to make sure this gets called whenever the
# interface header or the wrap library are updated. # interface header or the wrap library are updated.
# ~~~ # ~~~
# See: https://stackoverflow.com/questions/40032593/cmake-does-not-rebuild-dependent-after-prerequisite-changes # See: https://stackoverflow.com/questions/40032593/cmake-does-not-rebuild-dependent-after-prerequisite-changes
# ~~~ # ~~~
add_custom_command(OUTPUT ${generated_cpp} add_custom_command(
DEPENDS ${interface_header} OUTPUT ${cpp_files}
# @GTWRAP_SOURCE_DIR@/gtwrap/interface_parser.py DEPENDS ${interface_headers}
# @GTWRAP_SOURCE_DIR@/gtwrap/pybind_wrapper.py # @GTWRAP_SOURCE_DIR@/gtwrap/interface_parser.py
# @GTWRAP_SOURCE_DIR@/gtwrap/template_instantiator.py # @GTWRAP_SOURCE_DIR@/gtwrap/pybind_wrapper.py
APPEND) # @GTWRAP_SOURCE_DIR@/gtwrap/template_instantiator.py
APPEND)
pybind11_add_module(${target} ${generated_cpp}) pybind11_add_module(${target} "${cpp_files}")
if(APPLE) if(APPLE)
# `type_info` objects will become "weak private external" if the templated class is initialized implicitly even if we explicitly # `type_info` objects will become "weak private external" if the templated
# export them with `WRAP_EXPORT`. If that happens, the `type_info` for the same templated class will diverge between shared # class is initialized implicitly even if we explicitly export them with
# libraries, causing `dynamic_cast` to fail. This is mitigated by telling Clang to mimic the MSVC behavior. # `WRAP_EXPORT`. If that happens, the `type_info` for the same templated
# See https://developer.apple.com/library/archive/technotes/tn2185/_index.html#//apple_ref/doc/uid/DTS10004200-CH1-SUBSECTION2 # class will diverge between shared libraries, causing `dynamic_cast` to
# fail. This is mitigated by telling Clang to mimic the MSVC behavior. See
# https://developer.apple.com/library/archive/technotes/tn2185/_index.html#//apple_ref/doc/uid/DTS10004200-CH1-SUBSECTION2
# https://github.com/CppMicroServices/CppMicroServices/pull/82/files # https://github.com/CppMicroServices/CppMicroServices/pull/82/files
# https://www.russellmcc.com/posts/2013-08-03-rtti.html # https://www.russellmcc.com/posts/2013-08-03-rtti.html
target_compile_options(${target} PRIVATE "-fvisibility-ms-compat") target_compile_options(${target} PRIVATE "-fvisibility-ms-compat")
endif() endif()
add_dependencies(${target} pybind_wrap_${module_name}) add_dependencies(${target} pybind_wrap_${module_name})
if(NOT "${libs}" STREQUAL "") if(NOT "${libs}" STREQUAL "")
target_link_libraries(${target} PRIVATE "${libs}") target_link_libraries(${target} PRIVATE "${libs}")
endif() endif()
@ -121,10 +126,7 @@ endfunction()
# dest_directory: The destination directory to install to. # dest_directory: The destination directory to install to.
# patterns: list of file patterns to install # patterns: list of file patterns to install
# ~~~ # ~~~
function(install_python_scripts function(install_python_scripts source_directory dest_directory patterns)
source_directory
dest_directory
patterns)
set(patterns_args "") set(patterns_args "")
set(exclude_patterns "") set(exclude_patterns "")
@ -144,17 +146,19 @@ function(install_python_scripts
# there is one # there is one
get_filename_component(location "${dest_directory}" PATH) get_filename_component(location "${dest_directory}" PATH)
get_filename_component(name "${dest_directory}" NAME) get_filename_component(name "${dest_directory}" NAME)
install(DIRECTORY "${source_directory}" install(
DESTINATION "${location}/${name}${build_type_tag}" DIRECTORY "${source_directory}"
CONFIGURATIONS "${build_type}" DESTINATION "${location}/${name}${build_type_tag}"
FILES_MATCHING ${patterns_args} CONFIGURATIONS "${build_type}"
PATTERN "${exclude_patterns}" EXCLUDE) FILES_MATCHING ${patterns_args}
PATTERN "${exclude_patterns}" EXCLUDE)
endforeach() endforeach()
else() else()
install(DIRECTORY "${source_directory}" install(
DESTINATION "${dest_directory}" DIRECTORY "${source_directory}"
FILES_MATCHING ${patterns_args} DESTINATION "${dest_directory}"
PATTERN "${exclude_patterns}" EXCLUDE) FILES_MATCHING ${patterns_args}
PATTERN "${exclude_patterns}" EXCLUDE)
endif() endif()
endfunction() endfunction()
@ -172,13 +176,14 @@ function(install_python_files source_files dest_directory)
foreach(build_type ${CMAKE_CONFIGURATION_TYPES}) foreach(build_type ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER "${build_type}" build_type_upper) string(TOUPPER "${build_type}" build_type_upper)
set(build_type_tag "") set(build_type_tag "")
# Split up filename to strip trailing '/' in WRAP_PY_INSTALL_PATH if # Split up filename to strip trailing '/' in WRAP_PY_INSTALL_PATH if there
# there is one # is one
get_filename_component(location "${dest_directory}" PATH) get_filename_component(location "${dest_directory}" PATH)
get_filename_component(name "${dest_directory}" NAME) get_filename_component(name "${dest_directory}" NAME)
install(FILES "${source_files}" install(
DESTINATION "${location}/${name}${build_type_tag}" FILES "${source_files}"
CONFIGURATIONS "${build_type}") DESTINATION "${location}/${name}${build_type_tag}"
CONFIGURATIONS "${build_type}")
endforeach() endforeach()
else() else()
install(FILES "${source_files}" DESTINATION "${dest_directory}") install(FILES "${source_files}" DESTINATION "${dest_directory}")
@ -194,18 +199,19 @@ function(create_symlinks source_folder dest_folder)
return() return()
endif() endif()
file(GLOB files file(
LIST_DIRECTORIES true GLOB files
RELATIVE "${source_folder}" LIST_DIRECTORIES true
"${source_folder}/*") RELATIVE "${source_folder}"
"${source_folder}/*")
foreach(path_file ${files}) foreach(path_file ${files})
get_filename_component(folder ${path_file} PATH) get_filename_component(folder ${path_file} PATH)
get_filename_component(ext ${path_file} EXT) get_filename_component(ext ${path_file} EXT)
set(ignored_ext ".tpl" ".h") set(ignored_ext ".tpl" ".h")
list (FIND ignored_ext "${ext}" _index) list(FIND ignored_ext "${ext}" _index)
if (${_index} GREATER -1) if(${_index} GREATER -1)
continue() continue()
endif () endif()
# Create REAL folder # Create REAL folder
file(MAKE_DIRECTORY "${dest_folder}") file(MAKE_DIRECTORY "${dest_folder}")
@ -224,9 +230,10 @@ function(create_symlinks source_folder dest_folder)
endif() endif()
# cmake-format: on # cmake-format: on
execute_process(COMMAND ${command} execute_process(
RESULT_VARIABLE result COMMAND ${command}
ERROR_VARIABLE output) RESULT_VARIABLE result
ERROR_VARIABLE output)
if(NOT ${result} EQUAL 0) if(NOT ${result} EQUAL 0)
message( message(

View File

@ -12,7 +12,7 @@ Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellae
import sys import sys
import pyparsing import pyparsing # type: ignore
from .classes import * from .classes import *
from .declaration import * from .declaration import *

View File

@ -12,7 +12,7 @@ Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellae
from typing import Iterable, List, Union from typing import Iterable, List, Union
from pyparsing import Literal, Optional, ZeroOrMore from pyparsing import Literal, Optional, ZeroOrMore # type: ignore
from .enum import Enum from .enum import Enum
from .function import ArgumentList, ReturnType from .function import ArgumentList, ReturnType
@ -233,7 +233,7 @@ class Class:
self.static_methods = [] self.static_methods = []
self.properties = [] self.properties = []
self.operators = [] self.operators = []
self.enums = [] self.enums: List[Enum] = []
for m in members: for m in members:
if isinstance(m, Constructor): if isinstance(m, Constructor):
self.ctors.append(m) self.ctors.append(m)
@ -274,7 +274,7 @@ class Class:
def __init__( def __init__(
self, self,
template: Template, template: Union[Template, None],
is_virtual: str, is_virtual: str,
name: str, name: str,
parent_class: list, parent_class: list,
@ -292,16 +292,16 @@ class Class:
if parent_class: if parent_class:
# If it is in an iterable, extract the parent class. # If it is in an iterable, extract the parent class.
if isinstance(parent_class, Iterable): if isinstance(parent_class, Iterable):
parent_class = parent_class[0] parent_class = parent_class[0] # type: ignore
# If the base class is a TemplatedType, # If the base class is a TemplatedType,
# we want the instantiated Typename # we want the instantiated Typename
if isinstance(parent_class, TemplatedType): if isinstance(parent_class, TemplatedType):
parent_class = parent_class.typename parent_class = parent_class.typename # type: ignore
self.parent_class = parent_class self.parent_class = parent_class
else: else:
self.parent_class = '' self.parent_class = '' # type: ignore
self.ctors = ctors self.ctors = ctors
self.methods = methods self.methods = methods

View File

@ -10,7 +10,7 @@ Classes and rules for declarations such as includes and forward declarations.
Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert
""" """
from pyparsing import CharsNotIn, Optional from pyparsing import CharsNotIn, Optional # type: ignore
from .tokens import (CLASS, COLON, INCLUDE, LOPBRACK, ROPBRACK, SEMI_COLON, from .tokens import (CLASS, COLON, INCLUDE, LOPBRACK, ROPBRACK, SEMI_COLON,
VIRTUAL) VIRTUAL)

View File

@ -10,7 +10,7 @@ Parser class and rules for parsing C++ enums.
Author: Varun Agrawal Author: Varun Agrawal
""" """
from pyparsing import delimitedList from pyparsing import delimitedList # type: ignore
from .tokens import ENUM, IDENT, LBRACE, RBRACE, SEMI_COLON from .tokens import ENUM, IDENT, LBRACE, RBRACE, SEMI_COLON
from .type import Typename from .type import Typename

View File

@ -10,9 +10,9 @@ Parser classes and rules for parsing C++ functions.
Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert
""" """
from typing import Iterable, List, Union from typing import Any, Iterable, List, Union
from pyparsing import Optional, ParseResults, delimitedList from pyparsing import Optional, ParseResults, delimitedList # type: ignore
from .template import Template from .template import Template
from .tokens import (COMMA, DEFAULT_ARG, EQUAL, IDENT, LOPBRACK, LPAREN, PAIR, from .tokens import (COMMA, DEFAULT_ARG, EQUAL, IDENT, LOPBRACK, LPAREN, PAIR,
@ -42,12 +42,12 @@ class Argument:
name: str, name: str,
default: ParseResults = None): default: ParseResults = None):
if isinstance(ctype, Iterable): if isinstance(ctype, Iterable):
self.ctype = ctype[0] self.ctype = ctype[0] # type: ignore
else: else:
self.ctype = ctype self.ctype = ctype
self.name = name self.name = name
self.default = default self.default = default
self.parent = None # type: Union[ArgumentList, None] self.parent: Union[ArgumentList, None] = None
def __repr__(self) -> str: def __repr__(self) -> str:
return self.to_cpp() return self.to_cpp()
@ -70,7 +70,7 @@ class ArgumentList:
arg.parent = self arg.parent = self
# The parent object which contains the argument list # The parent object which contains the argument list
# E.g. Method, StaticMethod, Template, Constructor, GlobalFunction # E.g. Method, StaticMethod, Template, Constructor, GlobalFunction
self.parent = None self.parent: Any = None
@staticmethod @staticmethod
def from_parse_result(parse_result: ParseResults): def from_parse_result(parse_result: ParseResults):
@ -123,7 +123,7 @@ class ReturnType:
self.type2 = type2 self.type2 = type2
# The parent object which contains the return type # The parent object which contains the return type
# E.g. Method, StaticMethod, Template, Constructor, GlobalFunction # E.g. Method, StaticMethod, Template, Constructor, GlobalFunction
self.parent = None self.parent: Any = None
def is_void(self) -> bool: def is_void(self) -> bool:
""" """

View File

@ -12,7 +12,8 @@ Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellae
# pylint: disable=unnecessary-lambda, unused-import, expression-not-assigned, no-else-return, protected-access, too-few-public-methods, too-many-arguments # pylint: disable=unnecessary-lambda, unused-import, expression-not-assigned, no-else-return, protected-access, too-few-public-methods, too-many-arguments
from pyparsing import ParseResults, ZeroOrMore, cppStyleComment, stringEnd from pyparsing import (ParseResults, ZeroOrMore, # type: ignore
cppStyleComment, stringEnd)
from .classes import Class from .classes import Class
from .declaration import ForwardDeclaration, Include from .declaration import ForwardDeclaration, Include

View File

@ -14,7 +14,7 @@ Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellae
from typing import List, Union from typing import List, Union
from pyparsing import Forward, ParseResults, ZeroOrMore from pyparsing import Forward, ParseResults, ZeroOrMore # type: ignore
from .classes import Class, collect_namespaces from .classes import Class, collect_namespaces
from .declaration import ForwardDeclaration, Include from .declaration import ForwardDeclaration, Include
@ -93,7 +93,7 @@ class Namespace:
return Namespace(t.name, content) return Namespace(t.name, content)
def find_class_or_function( def find_class_or_function(
self, typename: Typename) -> Union[Class, GlobalFunction]: self, typename: Typename) -> Union[Class, GlobalFunction, ForwardDeclaration]:
""" """
Find the Class or GlobalFunction object given its typename. Find the Class or GlobalFunction object given its typename.
We have to traverse the tree of namespaces. We have to traverse the tree of namespaces.
@ -115,7 +115,7 @@ class Namespace:
return res[0] return res[0]
def top_level(self) -> "Namespace": def top_level(self) -> "Namespace":
"""Return the top leve namespace.""" """Return the top level namespace."""
if self.name == '' or self.parent == '': if self.name == '' or self.parent == '':
return self return self
else: else:

View File

@ -12,11 +12,11 @@ Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellae
from typing import List from typing import List
from pyparsing import Optional, ParseResults, delimitedList from pyparsing import Optional, ParseResults, delimitedList # type: ignore
from .tokens import (EQUAL, IDENT, LBRACE, LOPBRACK, RBRACE, ROPBRACK, from .tokens import (EQUAL, IDENT, LBRACE, LOPBRACK, RBRACE, ROPBRACK,
SEMI_COLON, TEMPLATE, TYPEDEF) SEMI_COLON, TEMPLATE, TYPEDEF)
from .type import Typename, TemplatedType from .type import TemplatedType, Typename
class Template: class Template:

View File

@ -10,9 +10,9 @@ All the token definitions.
Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellaert
""" """
from pyparsing import (Keyword, Literal, OneOrMore, Or, QuotedString, Suppress, from pyparsing import (Keyword, Literal, OneOrMore, Or, # type: ignore
Word, alphanums, alphas, nestedExpr, nums, QuotedString, Suppress, Word, alphanums, alphas,
originalTextFor, printables) nestedExpr, nums, originalTextFor, printables)
# rule for identifiers (e.g. variable names) # rule for identifiers (e.g. variable names)
IDENT = Word(alphas + '_', alphanums + '_') ^ Word(nums) IDENT = Word(alphas + '_', alphanums + '_') ^ Word(nums)

View File

@ -14,7 +14,8 @@ Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellae
from typing import Iterable, List, Union from typing import Iterable, List, Union
from pyparsing import Forward, Optional, Or, ParseResults, delimitedList from pyparsing import (Forward, Optional, Or, ParseResults, # type: ignore
delimitedList)
from .tokens import (BASIS_TYPES, CONST, IDENT, LOPBRACK, RAW_POINTER, REF, from .tokens import (BASIS_TYPES, CONST, IDENT, LOPBRACK, RAW_POINTER, REF,
ROPBRACK, SHARED_POINTER) ROPBRACK, SHARED_POINTER)
@ -48,7 +49,7 @@ class Typename:
def __init__(self, def __init__(self,
t: ParseResults, t: ParseResults,
instantiations: Union[tuple, list, str, ParseResults] = ()): instantiations: Iterable[ParseResults] = ()):
self.name = t[-1] # the name is the last element in this list self.name = t[-1] # the name is the last element in this list
self.namespaces = t[:-1] self.namespaces = t[:-1]

View File

@ -10,7 +10,9 @@ Parser classes and rules for parsing C++ variables.
Author: Varun Agrawal, Gerry Chen Author: Varun Agrawal, Gerry Chen
""" """
from pyparsing import Optional, ParseResults from typing import List
from pyparsing import Optional, ParseResults # type: ignore
from .tokens import DEFAULT_ARG, EQUAL, IDENT, SEMI_COLON from .tokens import DEFAULT_ARG, EQUAL, IDENT, SEMI_COLON
from .type import TemplatedType, Type from .type import TemplatedType, Type
@ -40,7 +42,7 @@ class Variable:
t.default[0] if isinstance(t.default, ParseResults) else None)) t.default[0] if isinstance(t.default, ParseResults) else None))
def __init__(self, def __init__(self,
ctype: Type, ctype: List[Type],
name: str, name: str,
default: ParseResults = None, default: ParseResults = None,
parent=''): parent=''):

View File

@ -0,0 +1,3 @@
"""Package to wrap C++ code to Matlab via MEX."""
from .wrapper import MatlabWrapper

View File

@ -0,0 +1,222 @@
"""Mixins for reducing the amount of boilerplate in the main wrapper class."""
import gtwrap.interface_parser as parser
import gtwrap.template_instantiator as instantiator
class CheckMixin:
"""Mixin to provide various checks."""
# Data types that are primitive types
not_ptr_type = ['int', 'double', 'bool', 'char', 'unsigned char', 'size_t']
# Ignore the namespace for these datatypes
ignore_namespace = ['Matrix', 'Vector', 'Point2', 'Point3']
# Methods that should be ignored
ignore_methods = ['pickle']
# Methods that should not be wrapped directly
whitelist = ['serializable', 'serialize']
# Datatypes that do not need to be checked in methods
not_check_type: list = []
def _has_serialization(self, cls):
for m in cls.methods:
if m.name in self.whitelist:
return True
return False
def is_shared_ptr(self, arg_type):
"""
Determine if the `interface_parser.Type` should be treated as a
shared pointer in the wrapper.
"""
return arg_type.is_shared_ptr or (
arg_type.typename.name not in self.not_ptr_type
and arg_type.typename.name not in self.ignore_namespace
and arg_type.typename.name != 'string')
def is_ptr(self, arg_type):
"""
Determine if the `interface_parser.Type` should be treated as a
raw pointer in the wrapper.
"""
return arg_type.is_ptr or (
arg_type.typename.name not in self.not_ptr_type
and arg_type.typename.name not in self.ignore_namespace
and arg_type.typename.name != 'string')
def is_ref(self, arg_type):
"""
Determine if the `interface_parser.Type` should be treated as a
reference in the wrapper.
"""
return arg_type.typename.name not in self.ignore_namespace and \
arg_type.typename.name not in self.not_ptr_type and \
arg_type.is_ref
class FormatMixin:
"""Mixin to provide formatting utilities."""
def _clean_class_name(self, instantiated_class):
"""Reformatted the C++ class name to fit Matlab defined naming
standards
"""
if len(instantiated_class.ctors) != 0:
return instantiated_class.ctors[0].name
return instantiated_class.name
def _format_type_name(self,
type_name,
separator='::',
include_namespace=True,
constructor=False,
method=False):
"""
Args:
type_name: an interface_parser.Typename to reformat
separator: the statement to add between namespaces and typename
include_namespace: whether to include namespaces when reformatting
constructor: if the typename will be in a constructor
method: if the typename will be in a method
Raises:
constructor and method cannot both be true
"""
if constructor and method:
raise ValueError(
'Constructor and method parameters cannot both be True')
formatted_type_name = ''
name = type_name.name
if include_namespace:
for namespace in type_name.namespaces:
if name not in self.ignore_namespace and namespace != '':
formatted_type_name += namespace + separator
if constructor:
formatted_type_name += self.data_type.get(name) or name
elif method:
formatted_type_name += self.data_type_param.get(name) or name
else:
formatted_type_name += name
if separator == "::": # C++
templates = []
for idx in range(len(type_name.instantiations)):
template = '{}'.format(
self._format_type_name(type_name.instantiations[idx],
include_namespace=include_namespace,
constructor=constructor,
method=method))
templates.append(template)
if len(templates) > 0: # If there are no templates
formatted_type_name += '<{}>'.format(','.join(templates))
else:
for idx in range(len(type_name.instantiations)):
formatted_type_name += '{}'.format(
self._format_type_name(type_name.instantiations[idx],
separator=separator,
include_namespace=False,
constructor=constructor,
method=method))
return formatted_type_name
def _format_return_type(self,
return_type,
include_namespace=False,
separator="::"):
"""Format return_type.
Args:
return_type: an interface_parser.ReturnType to reformat
include_namespace: whether to include namespaces when reformatting
"""
return_wrap = ''
if self._return_count(return_type) == 1:
return_wrap = self._format_type_name(
return_type.type1.typename,
separator=separator,
include_namespace=include_namespace)
else:
return_wrap = 'pair< {type1}, {type2} >'.format(
type1=self._format_type_name(
return_type.type1.typename,
separator=separator,
include_namespace=include_namespace),
type2=self._format_type_name(
return_type.type2.typename,
separator=separator,
include_namespace=include_namespace))
return return_wrap
def _format_class_name(self, instantiated_class, separator=''):
"""Format a template_instantiator.InstantiatedClass name."""
if instantiated_class.parent == '':
parent_full_ns = ['']
else:
parent_full_ns = instantiated_class.parent.full_namespaces()
# class_name = instantiated_class.parent.name
#
# if class_name != '':
# class_name += separator
#
# class_name += instantiated_class.name
parentname = "".join([separator + x
for x in parent_full_ns]) + separator
class_name = parentname[2 * len(separator):]
class_name += instantiated_class.name
return class_name
def _format_static_method(self, static_method, separator=''):
"""Example:
gtsamPoint3.staticFunction
"""
method = ''
if isinstance(static_method, parser.StaticMethod):
method += "".join([separator + x for x in static_method.parent.namespaces()]) + \
separator + static_method.parent.name + separator
return method[2 * len(separator):]
def _format_instance_method(self, instance_method, separator=''):
"""Example:
gtsamPoint3.staticFunction
"""
method = ''
if isinstance(instance_method, instantiator.InstantiatedMethod):
method_list = [
separator + x
for x in instance_method.parent.parent.full_namespaces()
]
method += "".join(method_list) + separator
method += instance_method.parent.name + separator
method += instance_method.original.name
method += "<" + instance_method.instantiations.to_cpp() + ">"
return method[2 * len(separator):]
def _format_global_method(self, static_method, separator=''):
"""Example:
gtsamPoint3.staticFunction
"""
method = ''
if isinstance(static_method, parser.GlobalFunction):
method += "".join([separator + x for x in static_method.parent.full_namespaces()]) + \
separator
return method[2 * len(separator):]

View File

@ -0,0 +1,166 @@
import textwrap
class WrapperTemplate:
"""Class to encapsulate string templates for use in wrapper generation"""
boost_headers = textwrap.dedent("""
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp>
""")
typdef_collectors = textwrap.dedent('''\
typedef std::set<boost::shared_ptr<{class_name_sep}>*> Collector_{class_name};
static Collector_{class_name} collector_{class_name};
''')
delete_obj = textwrap.indent(textwrap.dedent('''\
{{ for(Collector_{class_name}::iterator iter = collector_{class_name}.begin();
iter != collector_{class_name}.end(); ) {{
delete *iter;
collector_{class_name}.erase(iter++);
anyDeleted = true;
}} }}
'''),
prefix=' ')
delete_all_objects = textwrap.dedent('''
void _deleteAllObjects()
{{
mstream mout;
std::streambuf *outbuf = std::cout.rdbuf(&mout);\n
bool anyDeleted = false;
{delete_objs}
if(anyDeleted)
cout <<
"WARNING: Wrap modules with variables in the workspace have been reloaded due to\\n"
"calling destructors, call \'clear all\' again if you plan to now recompile a wrap\\n"
"module, so that your recompiled module is used instead of the old one." << endl;
std::cout.rdbuf(outbuf);
}}
''')
rtti_register = textwrap.dedent('''\
void _{module_name}_RTTIRegister() {{
const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_{module_name}_rttiRegistry_created");
if(!alreadyCreated) {{
std::map<std::string, std::string> types;
{rtti_classes}
mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry");
if(!registry)
registry = mxCreateStructMatrix(1, 1, 0, NULL);
typedef std::pair<std::string, std::string> StringPair;
for(const StringPair& rtti_matlab: types) {{
int fieldId = mxAddField(registry, rtti_matlab.first.c_str());
if(fieldId < 0) {{
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}}
mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str());
mxSetFieldByNumber(registry, 0, fieldId, matlabName);
}}
if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) {{
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}}
mxDestroyArray(registry);
mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL);
if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) {{
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}}
mxDestroyArray(newAlreadyCreated);
}}
}}
''')
collector_function_upcast_from_void = textwrap.dedent('''\
void {class_name}_upcastFromVoid_{id}(int nargout, mxArray *out[], int nargin, const mxArray *in[]) {{
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<{cpp_name}> Shared;
boost::shared_ptr<void> *asVoid = *reinterpret_cast<boost::shared_ptr<void>**> (mxGetData(in[0]));
out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
Shared *self = new Shared(boost::static_pointer_cast<{cpp_name}>(*asVoid));
*reinterpret_cast<Shared**>(mxGetData(out[0])) = self;
}}\n
''')
class_serialize_method = textwrap.dedent('''\
function varargout = string_serialize(this, varargin)
% STRING_SERIALIZE usage: string_serialize() : returns string
% Doxygen can be found at https://gtsam.org/doxygen/
if length(varargin) == 0
varargout{{1}} = {wrapper}({wrapper_id}, this, varargin{{:}});
else
error('Arguments do not match any overload of function {class_name}.string_serialize');
end
end\n
function sobj = saveobj(obj)
% SAVEOBJ Saves the object to a matlab-readable format
sobj = obj.string_serialize();
end
''')
collector_function_serialize = textwrap.indent(textwrap.dedent("""\
typedef boost::shared_ptr<{full_name}> Shared;
checkArguments("string_serialize",nargout,nargin-1,0);
Shared obj = unwrap_shared_ptr<{full_name}>(in[0], "ptr_{namespace}{class_name}");
ostringstream out_archive_stream;
boost::archive::text_oarchive out_archive(out_archive_stream);
out_archive << *obj;
out[0] = wrap< string >(out_archive_stream.str());
"""),
prefix=' ')
collector_function_deserialize = textwrap.indent(textwrap.dedent("""\
typedef boost::shared_ptr<{full_name}> Shared;
checkArguments("{namespace}{class_name}.string_deserialize",nargout,nargin,1);
string serialized = unwrap< string >(in[0]);
istringstream in_archive_stream(serialized);
boost::archive::text_iarchive in_archive(in_archive_stream);
Shared output(new {full_name}());
in_archive >> *output;
out[0] = wrap_shared_ptr(output,"{namespace}.{class_name}", false);
"""),
prefix=' ')
mex_function = textwrap.dedent('''
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{{
mstream mout;
std::streambuf *outbuf = std::cout.rdbuf(&mout);\n
_{module_name}_RTTIRegister();\n
int id = unwrap<int>(in[0]);\n
try {{
switch(id) {{
{cases} }}
}} catch(const std::exception& e) {{
mexErrMsgTxt(("Exception from gtsam:\\n" + std::string(e.what()) + "\\n").c_str());
}}\n
std::cout.rdbuf(outbuf);
}}
''')
collector_function_shared_return = textwrap.indent(textwrap.dedent('''\
{{
boost::shared_ptr<{name}> shared({shared_obj});
out[{id}] = wrap_shared_ptr(shared,"{name}");
}}{new_line}'''),
prefix=' ')
matlab_deserialize = textwrap.indent(textwrap.dedent("""\
function varargout = string_deserialize(varargin)
% STRING_DESERIALIZE usage: string_deserialize() : returns {class_name}
% Doxygen can be found at https://gtsam.org/doxygen/
if length(varargin) == 1
varargout{{1}} = {wrapper}({id}, varargin{{:}});
else
error('Arguments do not match any overload of function {class_name}.string_deserialize');
end
end\n
function obj = loadobj(sobj)
% LOADOBJ Saves the object to a matlab-readable format
obj = {class_name}.string_deserialize(sobj);
end
"""),
prefix=' ')

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@ Author: Duy Nguyen Ta, Fan Jiang, Matthew Sklar, Varun Agrawal, and Frank Dellae
# pylint: disable=too-many-arguments, too-many-instance-attributes, no-self-use, no-else-return, too-many-arguments, unused-format-string-argument, line-too-long # pylint: disable=too-many-arguments, too-many-instance-attributes, no-self-use, no-else-return, too-many-arguments, unused-format-string-argument, line-too-long
import re import re
from pathlib import Path
import gtwrap.interface_parser as parser import gtwrap.interface_parser as parser
import gtwrap.template_instantiator as instantiator import gtwrap.template_instantiator as instantiator
@ -32,7 +33,7 @@ class PybindWrapper:
self.top_module_namespaces = top_module_namespaces self.top_module_namespaces = top_module_namespaces
self.use_boost = use_boost self.use_boost = use_boost
self.ignore_classes = ignore_classes self.ignore_classes = ignore_classes
self._serializing_classes = list() self._serializing_classes = []
self.module_template = module_template self.module_template = module_template
self.python_keywords = [ self.python_keywords = [
'lambda', 'False', 'def', 'if', 'raise', 'None', 'del', 'import', 'lambda', 'False', 'def', 'if', 'raise', 'None', 'del', 'import',
@ -160,7 +161,7 @@ class PybindWrapper:
'self->print', 'self->print',
'py::scoped_ostream_redirect output; self->print') 'py::scoped_ostream_redirect output; self->print')
# Make __repr__() call print() internally # Make __repr__() call .print() internally
ret += '''{prefix}.def("__repr__", ret += '''{prefix}.def("__repr__",
[](const {cpp_class}& self{opt_comma}{args_signature_with_names}){{ [](const {cpp_class}& self{opt_comma}{args_signature_with_names}){{
gtsam::RedirectCout redirect; gtsam::RedirectCout redirect;
@ -557,8 +558,15 @@ class PybindWrapper:
) )
return wrapped, includes return wrapped, includes
def wrap(self, content): def wrap_file(self, content, module_name=None, submodules=None):
"""Wrap the code in the interface file.""" """
Wrap the code in the interface file.
Args:
content: The contents of the interface file.
module_name: The name of the module.
submodules: List of other interface file names that should be linked to.
"""
# Parse the contents of the interface file # Parse the contents of the interface file
module = parser.Module.parseString(content) module = parser.Module.parseString(content)
# Instantiate all templates # Instantiate all templates
@ -574,23 +582,74 @@ class PybindWrapper:
if ',' in cpp_class: if ',' in cpp_class:
new_name = re.sub("[,:<> ]", "", cpp_class) new_name = re.sub("[,:<> ]", "", cpp_class)
boost_class_export += "typedef {cpp_class} {new_name};\n".format( # noqa boost_class_export += "typedef {cpp_class} {new_name};\n".format( # noqa
cpp_class=cpp_class, cpp_class=cpp_class, new_name=new_name)
new_name=new_name,
)
boost_class_export += "BOOST_CLASS_EXPORT({new_name})\n".format( boost_class_export += "BOOST_CLASS_EXPORT({new_name})\n".format(
new_name=new_name, ) new_name=new_name, )
# Reset the serializing classes list
self._serializing_classes = []
holder_type = "PYBIND11_DECLARE_HOLDER_TYPE(TYPE_PLACEHOLDER_DONOTUSE, " \ holder_type = "PYBIND11_DECLARE_HOLDER_TYPE(TYPE_PLACEHOLDER_DONOTUSE, " \
"{shared_ptr_type}::shared_ptr<TYPE_PLACEHOLDER_DONOTUSE>);" "{shared_ptr_type}::shared_ptr<TYPE_PLACEHOLDER_DONOTUSE>);"
include_boost = "#include <boost/shared_ptr.hpp>" if self.use_boost else "" include_boost = "#include <boost/shared_ptr.hpp>" if self.use_boost else ""
submodules_init = []
if submodules is not None:
module_def = "PYBIND11_MODULE({0}, m_)".format(module_name)
for idx, submodule in enumerate(submodules):
submodules[idx] = "void {0}(py::module_ &);".format(submodule)
submodules_init.append("{0}(m_);".format(submodule))
else:
module_def = "void {0}(py::module_ &m_)".format(module_name)
submodules = []
return self.module_template.format( return self.module_template.format(
include_boost=include_boost, include_boost=include_boost,
module_name=self.module_name, module_def=module_def,
module_name=module_name,
includes=includes, includes=includes,
holder_type=holder_type.format( holder_type=holder_type.format(
shared_ptr_type=('boost' if self.use_boost else 'std')) shared_ptr_type=('boost' if self.use_boost else 'std'))
if self.use_boost else "", if self.use_boost else "",
wrapped_namespace=wrapped_namespace, wrapped_namespace=wrapped_namespace,
boost_class_export=boost_class_export, boost_class_export=boost_class_export,
submodules="\n".join(submodules),
submodules_init="\n".join(submodules_init),
) )
def wrap(self, sources, main_output):
"""
Wrap all the source interface files.
Args:
sources: List of all interface files.
main_output: The name for the main module.
"""
main_module = sources[0]
submodules = []
for source in sources[1:]:
filename = Path(source).name
module_name = Path(source).stem
# Read in the complete interface (.i) file
with open(source, "r") as f:
content = f.read()
submodules.append(module_name)
cc_content = self.wrap_file(content, module_name=module_name)
# Generate the C++ code which Pybind11 will use.
with open(filename.replace(".i", ".cpp"), "w") as f:
f.write(cc_content)
with open(main_module, "r") as f:
content = f.read()
cc_content = self.wrap_file(content,
module_name=self.module_name,
submodules=submodules)
# Generate the C++ code which Pybind11 will use.
with open(main_output, "w") as f:
f.write(cc_content)

View File

@ -4,7 +4,7 @@
import itertools import itertools
from copy import deepcopy from copy import deepcopy
from typing import List from typing import Iterable, List
import gtwrap.interface_parser as parser import gtwrap.interface_parser as parser
@ -29,12 +29,13 @@ def instantiate_type(ctype: parser.Type,
ctype = deepcopy(ctype) ctype = deepcopy(ctype)
# Check if the return type has template parameters # Check if the return type has template parameters
if len(ctype.typename.instantiations) > 0: if ctype.typename.instantiations:
for idx, instantiation in enumerate(ctype.typename.instantiations): for idx, instantiation in enumerate(ctype.typename.instantiations):
if instantiation.name in template_typenames: if instantiation.name in template_typenames:
template_idx = template_typenames.index(instantiation.name) template_idx = template_typenames.index(instantiation.name)
ctype.typename.instantiations[idx] = instantiations[ ctype.typename.instantiations[
template_idx] idx] = instantiations[ # type: ignore
template_idx]
return ctype return ctype
@ -212,7 +213,9 @@ class InstantiatedMethod(parser.Method):
void func(X x, Y y); void func(X x, Y y);
} }
""" """
def __init__(self, original, instantiations: List[parser.Typename] = ''): def __init__(self,
original,
instantiations: Iterable[parser.Typename] = ()):
self.original = original self.original = original
self.instantiations = instantiations self.instantiations = instantiations
self.template = '' self.template = ''
@ -278,7 +281,7 @@ class InstantiatedClass(parser.Class):
self.original = original self.original = original
self.instantiations = instantiations self.instantiations = instantiations
self.template = '' self.template = None
self.is_virtual = original.is_virtual self.is_virtual = original.is_virtual
self.parent_class = original.parent_class self.parent_class = original.parent_class
self.parent = original.parent self.parent = original.parent
@ -318,7 +321,7 @@ class InstantiatedClass(parser.Class):
self.methods = [] self.methods = []
for method in instantiated_methods: for method in instantiated_methods:
if not method.template: if not method.template:
self.methods.append(InstantiatedMethod(method, '')) self.methods.append(InstantiatedMethod(method, ()))
else: else:
instantiations = [] instantiations = []
# Get all combinations of template parameters # Get all combinations of template parameters
@ -342,9 +345,9 @@ class InstantiatedClass(parser.Class):
) )
def __repr__(self): def __repr__(self):
return "{virtual} class {name} [{cpp_class}]: {parent_class}\n"\ return "{virtual}Class {cpp_class} : {parent_class}\n"\
"{ctors}\n{static_methods}\n{methods}".format( "{ctors}\n{static_methods}\n{methods}\n{operators}".format(
virtual="virtual" if self.is_virtual else '', virtual="virtual " if self.is_virtual else '',
name=self.name, name=self.name,
cpp_class=self.to_cpp(), cpp_class=self.to_cpp(),
parent_class=self.parent, parent_class=self.parent,

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Helper script to wrap C++ to Matlab. Helper script to wrap C++ to Matlab.
This script is installed via CMake to the user's binary directory This script is installed via CMake to the user's binary directory
@ -7,19 +6,24 @@ and invoked during the wrapping by CMake.
""" """
import argparse import argparse
import os
import sys import sys
from gtwrap.matlab_wrapper import MatlabWrapper, generate_content from gtwrap.matlab_wrapper import MatlabWrapper
if __name__ == "__main__": if __name__ == "__main__":
arg_parser = argparse.ArgumentParser( arg_parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter) formatter_class=argparse.ArgumentDefaultsHelpFormatter)
arg_parser.add_argument("--src", type=str, required=True, arg_parser.add_argument("--src",
type=str,
required=True,
help="Input interface .h file.") help="Input interface .h file.")
arg_parser.add_argument("--module_name", type=str, required=True, arg_parser.add_argument("--module_name",
type=str,
required=True,
help="Name of the C++ class being wrapped.") help="Name of the C++ class being wrapped.")
arg_parser.add_argument("--out", type=str, required=True, arg_parser.add_argument("--out",
type=str,
required=True,
help="Name of the output folder.") help="Name of the output folder.")
arg_parser.add_argument( arg_parser.add_argument(
"--top_module_namespaces", "--top_module_namespaces",
@ -33,28 +37,22 @@ if __name__ == "__main__":
"`<module_name>.Class` of the corresponding C++ `ns1::ns2::ns3::Class`" "`<module_name>.Class` of the corresponding C++ `ns1::ns2::ns3::Class`"
", and `from <module_name> import ns4` gives you access to a Python " ", and `from <module_name> import ns4` gives you access to a Python "
"`ns4.Class` of the C++ `ns1::ns2::ns3::ns4::Class`. ") "`ns4.Class` of the C++ `ns1::ns2::ns3::ns4::Class`. ")
arg_parser.add_argument("--ignore", arg_parser.add_argument(
nargs='*', "--ignore",
type=str, nargs='*',
help="A space-separated list of classes to ignore. " type=str,
"Class names must include their full namespaces.") help="A space-separated list of classes to ignore. "
"Class names must include their full namespaces.")
args = arg_parser.parse_args() args = arg_parser.parse_args()
top_module_namespaces = args.top_module_namespaces.split("::") top_module_namespaces = args.top_module_namespaces.split("::")
if top_module_namespaces[0]: if top_module_namespaces[0]:
top_module_namespaces = [''] + top_module_namespaces top_module_namespaces = [''] + top_module_namespaces
with open(args.src, 'r') as f: print("[MatlabWrapper] Ignoring classes: {}".format(args.ignore), file=sys.stderr)
content = f.read()
if not os.path.exists(args.src):
os.mkdir(args.src)
print("Ignoring classes: {}".format(args.ignore), file=sys.stderr)
wrapper = MatlabWrapper(module_name=args.module_name, wrapper = MatlabWrapper(module_name=args.module_name,
top_module_namespace=top_module_namespaces, top_module_namespace=top_module_namespaces,
ignore_classes=args.ignore) ignore_classes=args.ignore)
cc_content = wrapper.wrap(content) sources = args.src.split(';')
cc_content = wrapper.wrap(sources, path=args.out)
generate_content(cc_content, args.out)

View File

@ -67,10 +67,6 @@ def main():
if top_module_namespaces[0]: if top_module_namespaces[0]:
top_module_namespaces = [''] + top_module_namespaces top_module_namespaces = [''] + top_module_namespaces
# Read in the complete interface (.i) file
with open(args.src, "r") as f:
content = f.read()
with open(args.template, "r") as f: with open(args.template, "r") as f:
template_content = f.read() template_content = f.read()
@ -83,11 +79,8 @@ def main():
) )
# Wrap the code and get back the cpp/cc code. # Wrap the code and get back the cpp/cc code.
cc_content = wrapper.wrap(content) sources = args.src.split(';')
wrapper.wrap(sources, args.out)
# Generate the C++ code which Pybind11 will use.
with open(args.out, "w") as f:
f.write(cc_content)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -7,7 +7,7 @@
#include <pybind11/iostream.h> #include <pybind11/iostream.h>
#include <pybind11/functional.h> #include <pybind11/functional.h>
#include "gtsam/base/serialization.h" #include "gtsam/base/serialization.h"
#include "gtsam/nonlinear/utilities.h" // for RedirectCout. #include "gtsam/base/utilities.h" // for RedirectCout.
{includes} {includes}
#include <boost/serialization/export.hpp> #include <boost/serialization/export.hpp>
@ -22,9 +22,13 @@ using namespace std;
namespace py = pybind11; namespace py = pybind11;
PYBIND11_MODULE({module_name}, m_) {{ {submodules}
{module_def} {{
m_.doc() = "pybind11 wrapper of {module_name}"; m_.doc() = "pybind11 wrapper of {module_name}";
{submodules_init}
{wrapped_namespace} {wrapped_namespace}
#include "python/specializations.h" #include "python/specializations.h"

View File

@ -0,0 +1,36 @@
%class Class1, see Doxygen page for details
%at https://gtsam.org/doxygen/
%
%-------Constructors-------
%Class1()
%
classdef Class1 < handle
properties
ptr_gtsamClass1 = 0
end
methods
function obj = Class1(varargin)
if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682)
my_ptr = varargin{2};
multiple_files_wrapper(0, my_ptr);
elseif nargin == 0
my_ptr = multiple_files_wrapper(1);
else
error('Arguments do not match any overload of gtsam.Class1 constructor');
end
obj.ptr_gtsamClass1 = my_ptr;
end
function delete(obj)
multiple_files_wrapper(2, obj.ptr_gtsamClass1);
end
function display(obj), obj.print(''); end
%DISPLAY Calls print on the object
function disp(obj), obj.display; end
%DISP Calls print on the object
end
methods(Static = true)
end
end

View File

@ -0,0 +1,36 @@
%class Class2, see Doxygen page for details
%at https://gtsam.org/doxygen/
%
%-------Constructors-------
%Class2()
%
classdef Class2 < handle
properties
ptr_gtsamClass2 = 0
end
methods
function obj = Class2(varargin)
if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682)
my_ptr = varargin{2};
multiple_files_wrapper(3, my_ptr);
elseif nargin == 0
my_ptr = multiple_files_wrapper(4);
else
error('Arguments do not match any overload of gtsam.Class2 constructor');
end
obj.ptr_gtsamClass2 = my_ptr;
end
function delete(obj)
multiple_files_wrapper(5, obj.ptr_gtsamClass2);
end
function display(obj), obj.print(''); end
%DISPLAY Calls print on the object
function disp(obj), obj.display; end
%DISP Calls print on the object
end
methods(Static = true)
end
end

View File

@ -0,0 +1,36 @@
%class ClassA, see Doxygen page for details
%at https://gtsam.org/doxygen/
%
%-------Constructors-------
%ClassA()
%
classdef ClassA < handle
properties
ptr_gtsamClassA = 0
end
methods
function obj = ClassA(varargin)
if nargin == 2 && isa(varargin{1}, 'uint64') && varargin{1} == uint64(5139824614673773682)
my_ptr = varargin{2};
multiple_files_wrapper(6, my_ptr);
elseif nargin == 0
my_ptr = multiple_files_wrapper(7);
else
error('Arguments do not match any overload of gtsam.ClassA constructor');
end
obj.ptr_gtsamClassA = my_ptr;
end
function delete(obj)
multiple_files_wrapper(8, obj.ptr_gtsamClassA);
end
function display(obj), obj.print(''); end
%DISPLAY Calls print on the object
function disp(obj), obj.display; end
%DISP Calls print on the object
end
methods(Static = true)
end
end

View File

@ -7,7 +7,6 @@
#include <folder/path/to/Test.h> #include <folder/path/to/Test.h>
typedef Fun<double> FunDouble; typedef Fun<double> FunDouble;
typedef PrimitiveRef<double> PrimitiveRefDouble; typedef PrimitiveRef<double> PrimitiveRefDouble;
typedef MyVector<3> MyVector3; typedef MyVector<3> MyVector3;
@ -16,7 +15,6 @@ typedef MultipleTemplates<int, double> MultipleTemplatesIntDouble;
typedef MultipleTemplates<int, float> MultipleTemplatesIntFloat; typedef MultipleTemplates<int, float> MultipleTemplatesIntFloat;
typedef MyFactor<gtsam::Pose2, gtsam::Matrix> MyFactorPosePoint2; typedef MyFactor<gtsam::Pose2, gtsam::Matrix> MyFactorPosePoint2;
typedef std::set<boost::shared_ptr<FunRange>*> Collector_FunRange; typedef std::set<boost::shared_ptr<FunRange>*> Collector_FunRange;
static Collector_FunRange collector_FunRange; static Collector_FunRange collector_FunRange;
typedef std::set<boost::shared_ptr<FunDouble>*> Collector_FunDouble; typedef std::set<boost::shared_ptr<FunDouble>*> Collector_FunDouble;
@ -38,6 +36,7 @@ static Collector_ForwardKinematics collector_ForwardKinematics;
typedef std::set<boost::shared_ptr<MyFactorPosePoint2>*> Collector_MyFactorPosePoint2; typedef std::set<boost::shared_ptr<MyFactorPosePoint2>*> Collector_MyFactorPosePoint2;
static Collector_MyFactorPosePoint2 collector_MyFactorPosePoint2; static Collector_MyFactorPosePoint2 collector_MyFactorPosePoint2;
void _deleteAllObjects() void _deleteAllObjects()
{ {
mstream mout; mstream mout;
@ -104,6 +103,7 @@ void _deleteAllObjects()
collector_MyFactorPosePoint2.erase(iter++); collector_MyFactorPosePoint2.erase(iter++);
anyDeleted = true; anyDeleted = true;
} } } }
if(anyDeleted) if(anyDeleted)
cout << cout <<
"WARNING: Wrap modules with variables in the workspace have been reloaded due to\n" "WARNING: Wrap modules with variables in the workspace have been reloaded due to\n"
@ -117,24 +117,29 @@ void _class_RTTIRegister() {
if(!alreadyCreated) { if(!alreadyCreated) {
std::map<std::string, std::string> types; std::map<std::string, std::string> types;
mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry"); mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry");
if(!registry) if(!registry)
registry = mxCreateStructMatrix(1, 1, 0, NULL); registry = mxCreateStructMatrix(1, 1, 0, NULL);
typedef std::pair<std::string, std::string> StringPair; typedef std::pair<std::string, std::string> StringPair;
for(const StringPair& rtti_matlab: types) { for(const StringPair& rtti_matlab: types) {
int fieldId = mxAddField(registry, rtti_matlab.first.c_str()); int fieldId = mxAddField(registry, rtti_matlab.first.c_str());
if(fieldId < 0) if(fieldId < 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str()); mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str());
mxSetFieldByNumber(registry, 0, fieldId, matlabName); mxSetFieldByNumber(registry, 0, fieldId, matlabName);
} }
if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(registry); mxDestroyArray(registry);
mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL); mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL);
if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(newAlreadyCreated); mxDestroyArray(newAlreadyCreated);
} }
} }

View File

@ -5,38 +5,11 @@
#include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp> #include <boost/serialization/export.hpp>
#include <folder/path/to/Test.h>
typedef Fun<double> FunDouble;
typedef PrimitiveRef<double> PrimitiveRefDouble;
typedef MyVector<3> MyVector3;
typedef MyVector<12> MyVector12;
typedef MultipleTemplates<int, double> MultipleTemplatesIntDouble;
typedef MultipleTemplates<int, float> MultipleTemplatesIntFloat;
typedef MyFactor<gtsam::Pose2, gtsam::Matrix> MyFactorPosePoint2;
typedef std::set<boost::shared_ptr<FunRange>*> Collector_FunRange;
static Collector_FunRange collector_FunRange;
typedef std::set<boost::shared_ptr<FunDouble>*> Collector_FunDouble;
static Collector_FunDouble collector_FunDouble;
typedef std::set<boost::shared_ptr<Test>*> Collector_Test;
static Collector_Test collector_Test;
typedef std::set<boost::shared_ptr<PrimitiveRefDouble>*> Collector_PrimitiveRefDouble;
static Collector_PrimitiveRefDouble collector_PrimitiveRefDouble;
typedef std::set<boost::shared_ptr<MyVector3>*> Collector_MyVector3;
static Collector_MyVector3 collector_MyVector3;
typedef std::set<boost::shared_ptr<MyVector12>*> Collector_MyVector12;
static Collector_MyVector12 collector_MyVector12;
typedef std::set<boost::shared_ptr<MultipleTemplatesIntDouble>*> Collector_MultipleTemplatesIntDouble;
static Collector_MultipleTemplatesIntDouble collector_MultipleTemplatesIntDouble;
typedef std::set<boost::shared_ptr<MultipleTemplatesIntFloat>*> Collector_MultipleTemplatesIntFloat;
static Collector_MultipleTemplatesIntFloat collector_MultipleTemplatesIntFloat;
typedef std::set<boost::shared_ptr<ForwardKinematics>*> Collector_ForwardKinematics;
static Collector_ForwardKinematics collector_ForwardKinematics;
typedef std::set<boost::shared_ptr<MyFactorPosePoint2>*> Collector_MyFactorPosePoint2;
static Collector_MyFactorPosePoint2 collector_MyFactorPosePoint2;
void _deleteAllObjects() void _deleteAllObjects()
{ {
@ -44,66 +17,7 @@ void _deleteAllObjects()
std::streambuf *outbuf = std::cout.rdbuf(&mout); std::streambuf *outbuf = std::cout.rdbuf(&mout);
bool anyDeleted = false; bool anyDeleted = false;
{ for(Collector_FunRange::iterator iter = collector_FunRange.begin();
iter != collector_FunRange.end(); ) {
delete *iter;
collector_FunRange.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_FunDouble::iterator iter = collector_FunDouble.begin();
iter != collector_FunDouble.end(); ) {
delete *iter;
collector_FunDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_Test::iterator iter = collector_Test.begin();
iter != collector_Test.end(); ) {
delete *iter;
collector_Test.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_PrimitiveRefDouble::iterator iter = collector_PrimitiveRefDouble.begin();
iter != collector_PrimitiveRefDouble.end(); ) {
delete *iter;
collector_PrimitiveRefDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyVector3::iterator iter = collector_MyVector3.begin();
iter != collector_MyVector3.end(); ) {
delete *iter;
collector_MyVector3.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyVector12::iterator iter = collector_MyVector12.begin();
iter != collector_MyVector12.end(); ) {
delete *iter;
collector_MyVector12.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MultipleTemplatesIntDouble::iterator iter = collector_MultipleTemplatesIntDouble.begin();
iter != collector_MultipleTemplatesIntDouble.end(); ) {
delete *iter;
collector_MultipleTemplatesIntDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MultipleTemplatesIntFloat::iterator iter = collector_MultipleTemplatesIntFloat.begin();
iter != collector_MultipleTemplatesIntFloat.end(); ) {
delete *iter;
collector_MultipleTemplatesIntFloat.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ForwardKinematics::iterator iter = collector_ForwardKinematics.begin();
iter != collector_ForwardKinematics.end(); ) {
delete *iter;
collector_ForwardKinematics.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyFactorPosePoint2::iterator iter = collector_MyFactorPosePoint2.begin();
iter != collector_MyFactorPosePoint2.end(); ) {
delete *iter;
collector_MyFactorPosePoint2.erase(iter++);
anyDeleted = true;
} }
if(anyDeleted) if(anyDeleted)
cout << cout <<
"WARNING: Wrap modules with variables in the workspace have been reloaded due to\n" "WARNING: Wrap modules with variables in the workspace have been reloaded due to\n"
@ -117,24 +31,29 @@ void _functions_RTTIRegister() {
if(!alreadyCreated) { if(!alreadyCreated) {
std::map<std::string, std::string> types; std::map<std::string, std::string> types;
mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry"); mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry");
if(!registry) if(!registry)
registry = mxCreateStructMatrix(1, 1, 0, NULL); registry = mxCreateStructMatrix(1, 1, 0, NULL);
typedef std::pair<std::string, std::string> StringPair; typedef std::pair<std::string, std::string> StringPair;
for(const StringPair& rtti_matlab: types) { for(const StringPair& rtti_matlab: types) {
int fieldId = mxAddField(registry, rtti_matlab.first.c_str()); int fieldId = mxAddField(registry, rtti_matlab.first.c_str());
if(fieldId < 0) if(fieldId < 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str()); mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str());
mxSetFieldByNumber(registry, 0, fieldId, matlabName); mxSetFieldByNumber(registry, 0, fieldId, matlabName);
} }
if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(registry); mxDestroyArray(registry);
mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL); mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL);
if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(newAlreadyCreated); mxDestroyArray(newAlreadyCreated);
} }
} }

View File

@ -5,112 +5,25 @@
#include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp> #include <boost/serialization/export.hpp>
#include <folder/path/to/Test.h>
#include <gtsam/geometry/Point2.h> #include <gtsam/geometry/Point2.h>
#include <gtsam/geometry/Point3.h> #include <gtsam/geometry/Point3.h>
typedef Fun<double> FunDouble;
typedef PrimitiveRef<double> PrimitiveRefDouble;
typedef MyVector<3> MyVector3;
typedef MyVector<12> MyVector12;
typedef MultipleTemplates<int, double> MultipleTemplatesIntDouble;
typedef MultipleTemplates<int, float> MultipleTemplatesIntFloat;
typedef MyFactor<gtsam::Pose2, gtsam::Matrix> MyFactorPosePoint2;
BOOST_CLASS_EXPORT_GUID(gtsam::Point2, "gtsamPoint2"); BOOST_CLASS_EXPORT_GUID(gtsam::Point2, "gtsamPoint2");
BOOST_CLASS_EXPORT_GUID(gtsam::Point3, "gtsamPoint3"); BOOST_CLASS_EXPORT_GUID(gtsam::Point3, "gtsamPoint3");
typedef std::set<boost::shared_ptr<FunRange>*> Collector_FunRange;
static Collector_FunRange collector_FunRange;
typedef std::set<boost::shared_ptr<FunDouble>*> Collector_FunDouble;
static Collector_FunDouble collector_FunDouble;
typedef std::set<boost::shared_ptr<Test>*> Collector_Test;
static Collector_Test collector_Test;
typedef std::set<boost::shared_ptr<PrimitiveRefDouble>*> Collector_PrimitiveRefDouble;
static Collector_PrimitiveRefDouble collector_PrimitiveRefDouble;
typedef std::set<boost::shared_ptr<MyVector3>*> Collector_MyVector3;
static Collector_MyVector3 collector_MyVector3;
typedef std::set<boost::shared_ptr<MyVector12>*> Collector_MyVector12;
static Collector_MyVector12 collector_MyVector12;
typedef std::set<boost::shared_ptr<MultipleTemplatesIntDouble>*> Collector_MultipleTemplatesIntDouble;
static Collector_MultipleTemplatesIntDouble collector_MultipleTemplatesIntDouble;
typedef std::set<boost::shared_ptr<MultipleTemplatesIntFloat>*> Collector_MultipleTemplatesIntFloat;
static Collector_MultipleTemplatesIntFloat collector_MultipleTemplatesIntFloat;
typedef std::set<boost::shared_ptr<ForwardKinematics>*> Collector_ForwardKinematics;
static Collector_ForwardKinematics collector_ForwardKinematics;
typedef std::set<boost::shared_ptr<MyFactorPosePoint2>*> Collector_MyFactorPosePoint2;
static Collector_MyFactorPosePoint2 collector_MyFactorPosePoint2;
typedef std::set<boost::shared_ptr<gtsam::Point2>*> Collector_gtsamPoint2; typedef std::set<boost::shared_ptr<gtsam::Point2>*> Collector_gtsamPoint2;
static Collector_gtsamPoint2 collector_gtsamPoint2; static Collector_gtsamPoint2 collector_gtsamPoint2;
typedef std::set<boost::shared_ptr<gtsam::Point3>*> Collector_gtsamPoint3; typedef std::set<boost::shared_ptr<gtsam::Point3>*> Collector_gtsamPoint3;
static Collector_gtsamPoint3 collector_gtsamPoint3; static Collector_gtsamPoint3 collector_gtsamPoint3;
void _deleteAllObjects() void _deleteAllObjects()
{ {
mstream mout; mstream mout;
std::streambuf *outbuf = std::cout.rdbuf(&mout); std::streambuf *outbuf = std::cout.rdbuf(&mout);
bool anyDeleted = false; bool anyDeleted = false;
{ for(Collector_FunRange::iterator iter = collector_FunRange.begin();
iter != collector_FunRange.end(); ) {
delete *iter;
collector_FunRange.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_FunDouble::iterator iter = collector_FunDouble.begin();
iter != collector_FunDouble.end(); ) {
delete *iter;
collector_FunDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_Test::iterator iter = collector_Test.begin();
iter != collector_Test.end(); ) {
delete *iter;
collector_Test.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_PrimitiveRefDouble::iterator iter = collector_PrimitiveRefDouble.begin();
iter != collector_PrimitiveRefDouble.end(); ) {
delete *iter;
collector_PrimitiveRefDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyVector3::iterator iter = collector_MyVector3.begin();
iter != collector_MyVector3.end(); ) {
delete *iter;
collector_MyVector3.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyVector12::iterator iter = collector_MyVector12.begin();
iter != collector_MyVector12.end(); ) {
delete *iter;
collector_MyVector12.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MultipleTemplatesIntDouble::iterator iter = collector_MultipleTemplatesIntDouble.begin();
iter != collector_MultipleTemplatesIntDouble.end(); ) {
delete *iter;
collector_MultipleTemplatesIntDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MultipleTemplatesIntFloat::iterator iter = collector_MultipleTemplatesIntFloat.begin();
iter != collector_MultipleTemplatesIntFloat.end(); ) {
delete *iter;
collector_MultipleTemplatesIntFloat.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ForwardKinematics::iterator iter = collector_ForwardKinematics.begin();
iter != collector_ForwardKinematics.end(); ) {
delete *iter;
collector_ForwardKinematics.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyFactorPosePoint2::iterator iter = collector_MyFactorPosePoint2.begin();
iter != collector_MyFactorPosePoint2.end(); ) {
delete *iter;
collector_MyFactorPosePoint2.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamPoint2::iterator iter = collector_gtsamPoint2.begin(); { for(Collector_gtsamPoint2::iterator iter = collector_gtsamPoint2.begin();
iter != collector_gtsamPoint2.end(); ) { iter != collector_gtsamPoint2.end(); ) {
delete *iter; delete *iter;
@ -123,6 +36,7 @@ void _deleteAllObjects()
collector_gtsamPoint3.erase(iter++); collector_gtsamPoint3.erase(iter++);
anyDeleted = true; anyDeleted = true;
} } } }
if(anyDeleted) if(anyDeleted)
cout << cout <<
"WARNING: Wrap modules with variables in the workspace have been reloaded due to\n" "WARNING: Wrap modules with variables in the workspace have been reloaded due to\n"
@ -136,24 +50,29 @@ void _geometry_RTTIRegister() {
if(!alreadyCreated) { if(!alreadyCreated) {
std::map<std::string, std::string> types; std::map<std::string, std::string> types;
mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry"); mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry");
if(!registry) if(!registry)
registry = mxCreateStructMatrix(1, 1, 0, NULL); registry = mxCreateStructMatrix(1, 1, 0, NULL);
typedef std::pair<std::string, std::string> StringPair; typedef std::pair<std::string, std::string> StringPair;
for(const StringPair& rtti_matlab: types) { for(const StringPair& rtti_matlab: types) {
int fieldId = mxAddField(registry, rtti_matlab.first.c_str()); int fieldId = mxAddField(registry, rtti_matlab.first.c_str());
if(fieldId < 0) if(fieldId < 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str()); mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str());
mxSetFieldByNumber(registry, 0, fieldId, matlabName); mxSetFieldByNumber(registry, 0, fieldId, matlabName);
} }
if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(registry); mxDestroyArray(registry);
mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL); mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL);
if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(newAlreadyCreated); mxDestroyArray(newAlreadyCreated);
} }
} }

View File

@ -5,47 +5,11 @@
#include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp> #include <boost/serialization/export.hpp>
#include <folder/path/to/Test.h>
#include <gtsam/geometry/Point2.h>
#include <gtsam/geometry/Point3.h>
typedef Fun<double> FunDouble;
typedef PrimitiveRef<double> PrimitiveRefDouble;
typedef MyVector<3> MyVector3;
typedef MyVector<12> MyVector12;
typedef MultipleTemplates<int, double> MultipleTemplatesIntDouble;
typedef MultipleTemplates<int, float> MultipleTemplatesIntFloat;
typedef MyFactor<gtsam::Pose2, gtsam::Matrix> MyFactorPosePoint2;
typedef MyTemplate<gtsam::Point2> MyTemplatePoint2; typedef MyTemplate<gtsam::Point2> MyTemplatePoint2;
typedef MyTemplate<gtsam::Matrix> MyTemplateMatrix; typedef MyTemplate<gtsam::Matrix> MyTemplateMatrix;
BOOST_CLASS_EXPORT_GUID(gtsam::Point2, "gtsamPoint2");
BOOST_CLASS_EXPORT_GUID(gtsam::Point3, "gtsamPoint3");
typedef std::set<boost::shared_ptr<FunRange>*> Collector_FunRange;
static Collector_FunRange collector_FunRange;
typedef std::set<boost::shared_ptr<FunDouble>*> Collector_FunDouble;
static Collector_FunDouble collector_FunDouble;
typedef std::set<boost::shared_ptr<Test>*> Collector_Test;
static Collector_Test collector_Test;
typedef std::set<boost::shared_ptr<PrimitiveRefDouble>*> Collector_PrimitiveRefDouble;
static Collector_PrimitiveRefDouble collector_PrimitiveRefDouble;
typedef std::set<boost::shared_ptr<MyVector3>*> Collector_MyVector3;
static Collector_MyVector3 collector_MyVector3;
typedef std::set<boost::shared_ptr<MyVector12>*> Collector_MyVector12;
static Collector_MyVector12 collector_MyVector12;
typedef std::set<boost::shared_ptr<MultipleTemplatesIntDouble>*> Collector_MultipleTemplatesIntDouble;
static Collector_MultipleTemplatesIntDouble collector_MultipleTemplatesIntDouble;
typedef std::set<boost::shared_ptr<MultipleTemplatesIntFloat>*> Collector_MultipleTemplatesIntFloat;
static Collector_MultipleTemplatesIntFloat collector_MultipleTemplatesIntFloat;
typedef std::set<boost::shared_ptr<ForwardKinematics>*> Collector_ForwardKinematics;
static Collector_ForwardKinematics collector_ForwardKinematics;
typedef std::set<boost::shared_ptr<MyFactorPosePoint2>*> Collector_MyFactorPosePoint2;
static Collector_MyFactorPosePoint2 collector_MyFactorPosePoint2;
typedef std::set<boost::shared_ptr<gtsam::Point2>*> Collector_gtsamPoint2;
static Collector_gtsamPoint2 collector_gtsamPoint2;
typedef std::set<boost::shared_ptr<gtsam::Point3>*> Collector_gtsamPoint3;
static Collector_gtsamPoint3 collector_gtsamPoint3;
typedef std::set<boost::shared_ptr<MyBase>*> Collector_MyBase; typedef std::set<boost::shared_ptr<MyBase>*> Collector_MyBase;
static Collector_MyBase collector_MyBase; static Collector_MyBase collector_MyBase;
typedef std::set<boost::shared_ptr<MyTemplatePoint2>*> Collector_MyTemplatePoint2; typedef std::set<boost::shared_ptr<MyTemplatePoint2>*> Collector_MyTemplatePoint2;
@ -55,84 +19,13 @@ static Collector_MyTemplateMatrix collector_MyTemplateMatrix;
typedef std::set<boost::shared_ptr<ForwardKinematicsFactor>*> Collector_ForwardKinematicsFactor; typedef std::set<boost::shared_ptr<ForwardKinematicsFactor>*> Collector_ForwardKinematicsFactor;
static Collector_ForwardKinematicsFactor collector_ForwardKinematicsFactor; static Collector_ForwardKinematicsFactor collector_ForwardKinematicsFactor;
void _deleteAllObjects() void _deleteAllObjects()
{ {
mstream mout; mstream mout;
std::streambuf *outbuf = std::cout.rdbuf(&mout); std::streambuf *outbuf = std::cout.rdbuf(&mout);
bool anyDeleted = false; bool anyDeleted = false;
{ for(Collector_FunRange::iterator iter = collector_FunRange.begin();
iter != collector_FunRange.end(); ) {
delete *iter;
collector_FunRange.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_FunDouble::iterator iter = collector_FunDouble.begin();
iter != collector_FunDouble.end(); ) {
delete *iter;
collector_FunDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_Test::iterator iter = collector_Test.begin();
iter != collector_Test.end(); ) {
delete *iter;
collector_Test.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_PrimitiveRefDouble::iterator iter = collector_PrimitiveRefDouble.begin();
iter != collector_PrimitiveRefDouble.end(); ) {
delete *iter;
collector_PrimitiveRefDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyVector3::iterator iter = collector_MyVector3.begin();
iter != collector_MyVector3.end(); ) {
delete *iter;
collector_MyVector3.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyVector12::iterator iter = collector_MyVector12.begin();
iter != collector_MyVector12.end(); ) {
delete *iter;
collector_MyVector12.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MultipleTemplatesIntDouble::iterator iter = collector_MultipleTemplatesIntDouble.begin();
iter != collector_MultipleTemplatesIntDouble.end(); ) {
delete *iter;
collector_MultipleTemplatesIntDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MultipleTemplatesIntFloat::iterator iter = collector_MultipleTemplatesIntFloat.begin();
iter != collector_MultipleTemplatesIntFloat.end(); ) {
delete *iter;
collector_MultipleTemplatesIntFloat.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ForwardKinematics::iterator iter = collector_ForwardKinematics.begin();
iter != collector_ForwardKinematics.end(); ) {
delete *iter;
collector_ForwardKinematics.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyFactorPosePoint2::iterator iter = collector_MyFactorPosePoint2.begin();
iter != collector_MyFactorPosePoint2.end(); ) {
delete *iter;
collector_MyFactorPosePoint2.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamPoint2::iterator iter = collector_gtsamPoint2.begin();
iter != collector_gtsamPoint2.end(); ) {
delete *iter;
collector_gtsamPoint2.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamPoint3::iterator iter = collector_gtsamPoint3.begin();
iter != collector_gtsamPoint3.end(); ) {
delete *iter;
collector_gtsamPoint3.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyBase::iterator iter = collector_MyBase.begin(); { for(Collector_MyBase::iterator iter = collector_MyBase.begin();
iter != collector_MyBase.end(); ) { iter != collector_MyBase.end(); ) {
delete *iter; delete *iter;
@ -157,6 +50,7 @@ void _deleteAllObjects()
collector_ForwardKinematicsFactor.erase(iter++); collector_ForwardKinematicsFactor.erase(iter++);
anyDeleted = true; anyDeleted = true;
} } } }
if(anyDeleted) if(anyDeleted)
cout << cout <<
"WARNING: Wrap modules with variables in the workspace have been reloaded due to\n" "WARNING: Wrap modules with variables in the workspace have been reloaded due to\n"
@ -169,42 +63,38 @@ void _inheritance_RTTIRegister() {
const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_inheritance_rttiRegistry_created"); const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_inheritance_rttiRegistry_created");
if(!alreadyCreated) { if(!alreadyCreated) {
std::map<std::string, std::string> types; std::map<std::string, std::string> types;
types.insert(std::make_pair(typeid(MyBase).name(), "MyBase")); types.insert(std::make_pair(typeid(MyBase).name(), "MyBase"));
types.insert(std::make_pair(typeid(MyTemplatePoint2).name(), "MyTemplatePoint2")); types.insert(std::make_pair(typeid(MyTemplatePoint2).name(), "MyTemplatePoint2"));
types.insert(std::make_pair(typeid(MyTemplateMatrix).name(), "MyTemplateMatrix")); types.insert(std::make_pair(typeid(MyTemplateMatrix).name(), "MyTemplateMatrix"));
types.insert(std::make_pair(typeid(ForwardKinematicsFactor).name(), "ForwardKinematicsFactor")); types.insert(std::make_pair(typeid(ForwardKinematicsFactor).name(), "ForwardKinematicsFactor"));
mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry"); mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry");
if(!registry) if(!registry)
registry = mxCreateStructMatrix(1, 1, 0, NULL); registry = mxCreateStructMatrix(1, 1, 0, NULL);
typedef std::pair<std::string, std::string> StringPair; typedef std::pair<std::string, std::string> StringPair;
for(const StringPair& rtti_matlab: types) { for(const StringPair& rtti_matlab: types) {
int fieldId = mxAddField(registry, rtti_matlab.first.c_str()); int fieldId = mxAddField(registry, rtti_matlab.first.c_str());
if(fieldId < 0) if(fieldId < 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str()); mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str());
mxSetFieldByNumber(registry, 0, fieldId, matlabName); mxSetFieldByNumber(registry, 0, fieldId, matlabName);
} }
if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(registry); mxDestroyArray(registry);
mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL); mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL);
if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(newAlreadyCreated); mxDestroyArray(newAlreadyCreated);
} }
} }
void gtsamPoint2_collectorInsertAndMakeBase_0(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<gtsam::Point2> Shared;
Shared *self = *reinterpret_cast<Shared**> (mxGetData(in[0]));
collector_gtsamPoint2.insert(self);
}
void MyBase_collectorInsertAndMakeBase_0(int nargout, mxArray *out[], int nargin, const mxArray *in[]) void MyBase_collectorInsertAndMakeBase_0(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{ {
mexAtExit(&_deleteAllObjects); mexAtExit(&_deleteAllObjects);
@ -214,6 +104,15 @@ void MyBase_collectorInsertAndMakeBase_0(int nargout, mxArray *out[], int nargin
collector_MyBase.insert(self); collector_MyBase.insert(self);
} }
void MyBase_upcastFromVoid_1(int nargout, mxArray *out[], int nargin, const mxArray *in[]) {
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<MyBase> Shared;
boost::shared_ptr<void> *asVoid = *reinterpret_cast<boost::shared_ptr<void>**> (mxGetData(in[0]));
out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
Shared *self = new Shared(boost::static_pointer_cast<MyBase>(*asVoid));
*reinterpret_cast<Shared**>(mxGetData(out[0])) = self;
}
void MyBase_deconstructor_2(int nargout, mxArray *out[], int nargin, const mxArray *in[]) void MyBase_deconstructor_2(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{ {
typedef boost::shared_ptr<MyBase> Shared; typedef boost::shared_ptr<MyBase> Shared;
@ -227,19 +126,6 @@ void MyBase_deconstructor_2(int nargout, mxArray *out[], int nargin, const mxArr
} }
} }
void gtsamPoint2_deconstructor_3(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
typedef boost::shared_ptr<gtsam::Point2> Shared;
checkArguments("delete_gtsamPoint2",nargout,nargin,1);
Shared *self = *reinterpret_cast<Shared**>(mxGetData(in[0]));
Collector_gtsamPoint2::iterator item;
item = collector_gtsamPoint2.find(self);
if(item != collector_gtsamPoint2.end()) {
delete self;
collector_gtsamPoint2.erase(item);
}
}
void MyTemplatePoint2_collectorInsertAndMakeBase_3(int nargout, mxArray *out[], int nargin, const mxArray *in[]) void MyTemplatePoint2_collectorInsertAndMakeBase_3(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{ {
mexAtExit(&_deleteAllObjects); mexAtExit(&_deleteAllObjects);
@ -253,6 +139,15 @@ void MyTemplatePoint2_collectorInsertAndMakeBase_3(int nargout, mxArray *out[],
*reinterpret_cast<SharedBase**>(mxGetData(out[0])) = new SharedBase(*self); *reinterpret_cast<SharedBase**>(mxGetData(out[0])) = new SharedBase(*self);
} }
void MyTemplatePoint2_upcastFromVoid_4(int nargout, mxArray *out[], int nargin, const mxArray *in[]) {
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<MyTemplate<gtsam::Point2>> Shared;
boost::shared_ptr<void> *asVoid = *reinterpret_cast<boost::shared_ptr<void>**> (mxGetData(in[0]));
out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
Shared *self = new Shared(boost::static_pointer_cast<MyTemplate<gtsam::Point2>>(*asVoid));
*reinterpret_cast<Shared**>(mxGetData(out[0])) = self;
}
void MyTemplatePoint2_constructor_5(int nargout, mxArray *out[], int nargin, const mxArray *in[]) void MyTemplatePoint2_constructor_5(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{ {
mexAtExit(&_deleteAllObjects); mexAtExit(&_deleteAllObjects);
@ -399,20 +294,6 @@ void MyTemplatePoint2_Level_18(int nargout, mxArray *out[], int nargin, const mx
out[0] = wrap_shared_ptr(boost::make_shared<MyTemplate<Point2>>(MyTemplate<gtsam::Point2>::Level(K)),"MyTemplatePoint2", false); out[0] = wrap_shared_ptr(boost::make_shared<MyTemplate<Point2>>(MyTemplate<gtsam::Point2>::Level(K)),"MyTemplatePoint2", false);
} }
void gtsamPoint3_constructor_19(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<gtsam::Point3> Shared;
double x = unwrap< double >(in[0]);
double y = unwrap< double >(in[1]);
double z = unwrap< double >(in[2]);
Shared *self = new Shared(new gtsam::Point3(x,y,z));
collector_gtsamPoint3.insert(self);
out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
*reinterpret_cast<Shared**> (mxGetData(out[0])) = self;
}
void MyTemplateMatrix_collectorInsertAndMakeBase_19(int nargout, mxArray *out[], int nargin, const mxArray *in[]) void MyTemplateMatrix_collectorInsertAndMakeBase_19(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{ {
mexAtExit(&_deleteAllObjects); mexAtExit(&_deleteAllObjects);
@ -426,6 +307,15 @@ void MyTemplateMatrix_collectorInsertAndMakeBase_19(int nargout, mxArray *out[],
*reinterpret_cast<SharedBase**>(mxGetData(out[0])) = new SharedBase(*self); *reinterpret_cast<SharedBase**>(mxGetData(out[0])) = new SharedBase(*self);
} }
void MyTemplateMatrix_upcastFromVoid_20(int nargout, mxArray *out[], int nargin, const mxArray *in[]) {
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<MyTemplate<gtsam::Matrix>> Shared;
boost::shared_ptr<void> *asVoid = *reinterpret_cast<boost::shared_ptr<void>**> (mxGetData(in[0]));
out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
Shared *self = new Shared(boost::static_pointer_cast<MyTemplate<gtsam::Matrix>>(*asVoid));
*reinterpret_cast<Shared**>(mxGetData(out[0])) = self;
}
void MyTemplateMatrix_constructor_21(int nargout, mxArray *out[], int nargin, const mxArray *in[]) void MyTemplateMatrix_constructor_21(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{ {
mexAtExit(&_deleteAllObjects); mexAtExit(&_deleteAllObjects);
@ -572,14 +462,6 @@ void MyTemplateMatrix_Level_34(int nargout, mxArray *out[], int nargin, const mx
out[0] = wrap_shared_ptr(boost::make_shared<MyTemplate<Matrix>>(MyTemplate<gtsam::Matrix>::Level(K)),"MyTemplateMatrix", false); out[0] = wrap_shared_ptr(boost::make_shared<MyTemplate<Matrix>>(MyTemplate<gtsam::Matrix>::Level(K)),"MyTemplateMatrix", false);
} }
void Test_return_vector2_35(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
checkArguments("return_vector2",nargout,nargin-1,1);
auto obj = unwrap_shared_ptr<Test>(in[0], "ptr_Test");
Vector value = unwrap< Vector >(in[1]);
out[0] = wrap< Vector >(obj->return_vector2(value));
}
void ForwardKinematicsFactor_collectorInsertAndMakeBase_35(int nargout, mxArray *out[], int nargin, const mxArray *in[]) void ForwardKinematicsFactor_collectorInsertAndMakeBase_35(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{ {
mexAtExit(&_deleteAllObjects); mexAtExit(&_deleteAllObjects);
@ -593,6 +475,15 @@ void ForwardKinematicsFactor_collectorInsertAndMakeBase_35(int nargout, mxArray
*reinterpret_cast<SharedBase**>(mxGetData(out[0])) = new SharedBase(*self); *reinterpret_cast<SharedBase**>(mxGetData(out[0])) = new SharedBase(*self);
} }
void ForwardKinematicsFactor_upcastFromVoid_36(int nargout, mxArray *out[], int nargin, const mxArray *in[]) {
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<ForwardKinematicsFactor> Shared;
boost::shared_ptr<void> *asVoid = *reinterpret_cast<boost::shared_ptr<void>**> (mxGetData(in[0]));
out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
Shared *self = new Shared(boost::static_pointer_cast<ForwardKinematicsFactor>(*asVoid));
*reinterpret_cast<Shared**>(mxGetData(out[0])) = self;
}
void ForwardKinematicsFactor_deconstructor_37(int nargout, mxArray *out[], int nargin, const mxArray *in[]) void ForwardKinematicsFactor_deconstructor_37(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{ {
typedef boost::shared_ptr<ForwardKinematicsFactor> Shared; typedef boost::shared_ptr<ForwardKinematicsFactor> Shared;
@ -619,19 +510,19 @@ void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
try { try {
switch(id) { switch(id) {
case 0: case 0:
gtsamPoint2_collectorInsertAndMakeBase_0(nargout, out, nargin-1, in+1); MyBase_collectorInsertAndMakeBase_0(nargout, out, nargin-1, in+1);
break; break;
case 1: case 1:
MyBase_collectorInsertAndMakeBase_0(nargout, out, nargin-1, in+1); MyBase_upcastFromVoid_1(nargout, out, nargin-1, in+1);
break; break;
case 2: case 2:
MyBase_deconstructor_2(nargout, out, nargin-1, in+1); MyBase_deconstructor_2(nargout, out, nargin-1, in+1);
break; break;
case 3: case 3:
gtsamPoint2_deconstructor_3(nargout, out, nargin-1, in+1); MyTemplatePoint2_collectorInsertAndMakeBase_3(nargout, out, nargin-1, in+1);
break; break;
case 4: case 4:
MyTemplatePoint2_collectorInsertAndMakeBase_3(nargout, out, nargin-1, in+1); MyTemplatePoint2_upcastFromVoid_4(nargout, out, nargin-1, in+1);
break; break;
case 5: case 5:
MyTemplatePoint2_constructor_5(nargout, out, nargin-1, in+1); MyTemplatePoint2_constructor_5(nargout, out, nargin-1, in+1);
@ -676,10 +567,10 @@ void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
MyTemplatePoint2_Level_18(nargout, out, nargin-1, in+1); MyTemplatePoint2_Level_18(nargout, out, nargin-1, in+1);
break; break;
case 19: case 19:
gtsamPoint3_constructor_19(nargout, out, nargin-1, in+1); MyTemplateMatrix_collectorInsertAndMakeBase_19(nargout, out, nargin-1, in+1);
break; break;
case 20: case 20:
MyTemplateMatrix_collectorInsertAndMakeBase_19(nargout, out, nargin-1, in+1); MyTemplateMatrix_upcastFromVoid_20(nargout, out, nargin-1, in+1);
break; break;
case 21: case 21:
MyTemplateMatrix_constructor_21(nargout, out, nargin-1, in+1); MyTemplateMatrix_constructor_21(nargout, out, nargin-1, in+1);
@ -724,10 +615,10 @@ void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
MyTemplateMatrix_Level_34(nargout, out, nargin-1, in+1); MyTemplateMatrix_Level_34(nargout, out, nargin-1, in+1);
break; break;
case 35: case 35:
Test_return_vector2_35(nargout, out, nargin-1, in+1); ForwardKinematicsFactor_collectorInsertAndMakeBase_35(nargout, out, nargin-1, in+1);
break; break;
case 36: case 36:
ForwardKinematicsFactor_collectorInsertAndMakeBase_35(nargout, out, nargin-1, in+1); ForwardKinematicsFactor_upcastFromVoid_36(nargout, out, nargin-1, in+1);
break; break;
case 37: case 37:
ForwardKinematicsFactor_deconstructor_37(nargout, out, nargin-1, in+1); ForwardKinematicsFactor_deconstructor_37(nargout, out, nargin-1, in+1);

View File

@ -0,0 +1,229 @@
#include <gtwrap/matlab.h>
#include <map>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp>
typedef std::set<boost::shared_ptr<gtsam::Class1>*> Collector_gtsamClass1;
static Collector_gtsamClass1 collector_gtsamClass1;
typedef std::set<boost::shared_ptr<gtsam::Class2>*> Collector_gtsamClass2;
static Collector_gtsamClass2 collector_gtsamClass2;
typedef std::set<boost::shared_ptr<gtsam::ClassA>*> Collector_gtsamClassA;
static Collector_gtsamClassA collector_gtsamClassA;
void _deleteAllObjects()
{
mstream mout;
std::streambuf *outbuf = std::cout.rdbuf(&mout);
bool anyDeleted = false;
{ for(Collector_gtsamClass1::iterator iter = collector_gtsamClass1.begin();
iter != collector_gtsamClass1.end(); ) {
delete *iter;
collector_gtsamClass1.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamClass2::iterator iter = collector_gtsamClass2.begin();
iter != collector_gtsamClass2.end(); ) {
delete *iter;
collector_gtsamClass2.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamClassA::iterator iter = collector_gtsamClassA.begin();
iter != collector_gtsamClassA.end(); ) {
delete *iter;
collector_gtsamClassA.erase(iter++);
anyDeleted = true;
} }
if(anyDeleted)
cout <<
"WARNING: Wrap modules with variables in the workspace have been reloaded due to\n"
"calling destructors, call 'clear all' again if you plan to now recompile a wrap\n"
"module, so that your recompiled module is used instead of the old one." << endl;
std::cout.rdbuf(outbuf);
}
void _multiple_files_RTTIRegister() {
const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_multiple_files_rttiRegistry_created");
if(!alreadyCreated) {
std::map<std::string, std::string> types;
mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry");
if(!registry)
registry = mxCreateStructMatrix(1, 1, 0, NULL);
typedef std::pair<std::string, std::string> StringPair;
for(const StringPair& rtti_matlab: types) {
int fieldId = mxAddField(registry, rtti_matlab.first.c_str());
if(fieldId < 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str());
mxSetFieldByNumber(registry, 0, fieldId, matlabName);
}
if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(registry);
mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL);
if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(newAlreadyCreated);
}
}
void gtsamClass1_collectorInsertAndMakeBase_0(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<gtsam::Class1> Shared;
Shared *self = *reinterpret_cast<Shared**> (mxGetData(in[0]));
collector_gtsamClass1.insert(self);
}
void gtsamClass1_constructor_1(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<gtsam::Class1> Shared;
Shared *self = new Shared(new gtsam::Class1());
collector_gtsamClass1.insert(self);
out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
*reinterpret_cast<Shared**> (mxGetData(out[0])) = self;
}
void gtsamClass1_deconstructor_2(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
typedef boost::shared_ptr<gtsam::Class1> Shared;
checkArguments("delete_gtsamClass1",nargout,nargin,1);
Shared *self = *reinterpret_cast<Shared**>(mxGetData(in[0]));
Collector_gtsamClass1::iterator item;
item = collector_gtsamClass1.find(self);
if(item != collector_gtsamClass1.end()) {
delete self;
collector_gtsamClass1.erase(item);
}
}
void gtsamClass2_collectorInsertAndMakeBase_3(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<gtsam::Class2> Shared;
Shared *self = *reinterpret_cast<Shared**> (mxGetData(in[0]));
collector_gtsamClass2.insert(self);
}
void gtsamClass2_constructor_4(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<gtsam::Class2> Shared;
Shared *self = new Shared(new gtsam::Class2());
collector_gtsamClass2.insert(self);
out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
*reinterpret_cast<Shared**> (mxGetData(out[0])) = self;
}
void gtsamClass2_deconstructor_5(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
typedef boost::shared_ptr<gtsam::Class2> Shared;
checkArguments("delete_gtsamClass2",nargout,nargin,1);
Shared *self = *reinterpret_cast<Shared**>(mxGetData(in[0]));
Collector_gtsamClass2::iterator item;
item = collector_gtsamClass2.find(self);
if(item != collector_gtsamClass2.end()) {
delete self;
collector_gtsamClass2.erase(item);
}
}
void gtsamClassA_collectorInsertAndMakeBase_6(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<gtsam::ClassA> Shared;
Shared *self = *reinterpret_cast<Shared**> (mxGetData(in[0]));
collector_gtsamClassA.insert(self);
}
void gtsamClassA_constructor_7(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
mexAtExit(&_deleteAllObjects);
typedef boost::shared_ptr<gtsam::ClassA> Shared;
Shared *self = new Shared(new gtsam::ClassA());
collector_gtsamClassA.insert(self);
out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
*reinterpret_cast<Shared**> (mxGetData(out[0])) = self;
}
void gtsamClassA_deconstructor_8(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
typedef boost::shared_ptr<gtsam::ClassA> Shared;
checkArguments("delete_gtsamClassA",nargout,nargin,1);
Shared *self = *reinterpret_cast<Shared**>(mxGetData(in[0]));
Collector_gtsamClassA::iterator item;
item = collector_gtsamClassA.find(self);
if(item != collector_gtsamClassA.end()) {
delete self;
collector_gtsamClassA.erase(item);
}
}
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
{
mstream mout;
std::streambuf *outbuf = std::cout.rdbuf(&mout);
_multiple_files_RTTIRegister();
int id = unwrap<int>(in[0]);
try {
switch(id) {
case 0:
gtsamClass1_collectorInsertAndMakeBase_0(nargout, out, nargin-1, in+1);
break;
case 1:
gtsamClass1_constructor_1(nargout, out, nargin-1, in+1);
break;
case 2:
gtsamClass1_deconstructor_2(nargout, out, nargin-1, in+1);
break;
case 3:
gtsamClass2_collectorInsertAndMakeBase_3(nargout, out, nargin-1, in+1);
break;
case 4:
gtsamClass2_constructor_4(nargout, out, nargin-1, in+1);
break;
case 5:
gtsamClass2_deconstructor_5(nargout, out, nargin-1, in+1);
break;
case 6:
gtsamClassA_collectorInsertAndMakeBase_6(nargout, out, nargin-1, in+1);
break;
case 7:
gtsamClassA_constructor_7(nargout, out, nargin-1, in+1);
break;
case 8:
gtsamClassA_deconstructor_8(nargout, out, nargin-1, in+1);
break;
}
} catch(const std::exception& e) {
mexErrMsgTxt(("Exception from gtsam:\n" + std::string(e.what()) + "\n").c_str());
}
std::cout.rdbuf(outbuf);
}

View File

@ -5,9 +5,6 @@
#include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp> #include <boost/serialization/export.hpp>
#include <folder/path/to/Test.h>
#include <gtsam/geometry/Point2.h>
#include <gtsam/geometry/Point3.h>
#include <gtsam/nonlinear/Values.h> #include <gtsam/nonlinear/Values.h>
#include <path/to/ns1.h> #include <path/to/ns1.h>
#include <path/to/ns1/ClassB.h> #include <path/to/ns1/ClassB.h>
@ -15,51 +12,8 @@
#include <path/to/ns2/ClassA.h> #include <path/to/ns2/ClassA.h>
#include <path/to/ns3.h> #include <path/to/ns3.h>
typedef Fun<double> FunDouble;
typedef PrimitiveRef<double> PrimitiveRefDouble;
typedef MyVector<3> MyVector3;
typedef MyVector<12> MyVector12;
typedef MultipleTemplates<int, double> MultipleTemplatesIntDouble;
typedef MultipleTemplates<int, float> MultipleTemplatesIntFloat;
typedef MyFactor<gtsam::Pose2, gtsam::Matrix> MyFactorPosePoint2;
typedef MyTemplate<gtsam::Point2> MyTemplatePoint2;
typedef MyTemplate<gtsam::Matrix> MyTemplateMatrix;
BOOST_CLASS_EXPORT_GUID(gtsam::Point2, "gtsamPoint2");
BOOST_CLASS_EXPORT_GUID(gtsam::Point3, "gtsamPoint3");
typedef std::set<boost::shared_ptr<FunRange>*> Collector_FunRange;
static Collector_FunRange collector_FunRange;
typedef std::set<boost::shared_ptr<FunDouble>*> Collector_FunDouble;
static Collector_FunDouble collector_FunDouble;
typedef std::set<boost::shared_ptr<Test>*> Collector_Test;
static Collector_Test collector_Test;
typedef std::set<boost::shared_ptr<PrimitiveRefDouble>*> Collector_PrimitiveRefDouble;
static Collector_PrimitiveRefDouble collector_PrimitiveRefDouble;
typedef std::set<boost::shared_ptr<MyVector3>*> Collector_MyVector3;
static Collector_MyVector3 collector_MyVector3;
typedef std::set<boost::shared_ptr<MyVector12>*> Collector_MyVector12;
static Collector_MyVector12 collector_MyVector12;
typedef std::set<boost::shared_ptr<MultipleTemplatesIntDouble>*> Collector_MultipleTemplatesIntDouble;
static Collector_MultipleTemplatesIntDouble collector_MultipleTemplatesIntDouble;
typedef std::set<boost::shared_ptr<MultipleTemplatesIntFloat>*> Collector_MultipleTemplatesIntFloat;
static Collector_MultipleTemplatesIntFloat collector_MultipleTemplatesIntFloat;
typedef std::set<boost::shared_ptr<ForwardKinematics>*> Collector_ForwardKinematics;
static Collector_ForwardKinematics collector_ForwardKinematics;
typedef std::set<boost::shared_ptr<MyFactorPosePoint2>*> Collector_MyFactorPosePoint2;
static Collector_MyFactorPosePoint2 collector_MyFactorPosePoint2;
typedef std::set<boost::shared_ptr<gtsam::Point2>*> Collector_gtsamPoint2;
static Collector_gtsamPoint2 collector_gtsamPoint2;
typedef std::set<boost::shared_ptr<gtsam::Point3>*> Collector_gtsamPoint3;
static Collector_gtsamPoint3 collector_gtsamPoint3;
typedef std::set<boost::shared_ptr<MyBase>*> Collector_MyBase;
static Collector_MyBase collector_MyBase;
typedef std::set<boost::shared_ptr<MyTemplatePoint2>*> Collector_MyTemplatePoint2;
static Collector_MyTemplatePoint2 collector_MyTemplatePoint2;
typedef std::set<boost::shared_ptr<MyTemplateMatrix>*> Collector_MyTemplateMatrix;
static Collector_MyTemplateMatrix collector_MyTemplateMatrix;
typedef std::set<boost::shared_ptr<ForwardKinematicsFactor>*> Collector_ForwardKinematicsFactor;
static Collector_ForwardKinematicsFactor collector_ForwardKinematicsFactor;
typedef std::set<boost::shared_ptr<ns1::ClassA>*> Collector_ns1ClassA; typedef std::set<boost::shared_ptr<ns1::ClassA>*> Collector_ns1ClassA;
static Collector_ns1ClassA collector_ns1ClassA; static Collector_ns1ClassA collector_ns1ClassA;
typedef std::set<boost::shared_ptr<ns1::ClassB>*> Collector_ns1ClassB; typedef std::set<boost::shared_ptr<ns1::ClassB>*> Collector_ns1ClassB;
@ -75,108 +29,13 @@ static Collector_ClassD collector_ClassD;
typedef std::set<boost::shared_ptr<gtsam::Values>*> Collector_gtsamValues; typedef std::set<boost::shared_ptr<gtsam::Values>*> Collector_gtsamValues;
static Collector_gtsamValues collector_gtsamValues; static Collector_gtsamValues collector_gtsamValues;
void _deleteAllObjects() void _deleteAllObjects()
{ {
mstream mout; mstream mout;
std::streambuf *outbuf = std::cout.rdbuf(&mout); std::streambuf *outbuf = std::cout.rdbuf(&mout);
bool anyDeleted = false; bool anyDeleted = false;
{ for(Collector_FunRange::iterator iter = collector_FunRange.begin();
iter != collector_FunRange.end(); ) {
delete *iter;
collector_FunRange.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_FunDouble::iterator iter = collector_FunDouble.begin();
iter != collector_FunDouble.end(); ) {
delete *iter;
collector_FunDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_Test::iterator iter = collector_Test.begin();
iter != collector_Test.end(); ) {
delete *iter;
collector_Test.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_PrimitiveRefDouble::iterator iter = collector_PrimitiveRefDouble.begin();
iter != collector_PrimitiveRefDouble.end(); ) {
delete *iter;
collector_PrimitiveRefDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyVector3::iterator iter = collector_MyVector3.begin();
iter != collector_MyVector3.end(); ) {
delete *iter;
collector_MyVector3.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyVector12::iterator iter = collector_MyVector12.begin();
iter != collector_MyVector12.end(); ) {
delete *iter;
collector_MyVector12.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MultipleTemplatesIntDouble::iterator iter = collector_MultipleTemplatesIntDouble.begin();
iter != collector_MultipleTemplatesIntDouble.end(); ) {
delete *iter;
collector_MultipleTemplatesIntDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MultipleTemplatesIntFloat::iterator iter = collector_MultipleTemplatesIntFloat.begin();
iter != collector_MultipleTemplatesIntFloat.end(); ) {
delete *iter;
collector_MultipleTemplatesIntFloat.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ForwardKinematics::iterator iter = collector_ForwardKinematics.begin();
iter != collector_ForwardKinematics.end(); ) {
delete *iter;
collector_ForwardKinematics.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyFactorPosePoint2::iterator iter = collector_MyFactorPosePoint2.begin();
iter != collector_MyFactorPosePoint2.end(); ) {
delete *iter;
collector_MyFactorPosePoint2.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamPoint2::iterator iter = collector_gtsamPoint2.begin();
iter != collector_gtsamPoint2.end(); ) {
delete *iter;
collector_gtsamPoint2.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamPoint3::iterator iter = collector_gtsamPoint3.begin();
iter != collector_gtsamPoint3.end(); ) {
delete *iter;
collector_gtsamPoint3.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyBase::iterator iter = collector_MyBase.begin();
iter != collector_MyBase.end(); ) {
delete *iter;
collector_MyBase.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyTemplatePoint2::iterator iter = collector_MyTemplatePoint2.begin();
iter != collector_MyTemplatePoint2.end(); ) {
delete *iter;
collector_MyTemplatePoint2.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyTemplateMatrix::iterator iter = collector_MyTemplateMatrix.begin();
iter != collector_MyTemplateMatrix.end(); ) {
delete *iter;
collector_MyTemplateMatrix.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ForwardKinematicsFactor::iterator iter = collector_ForwardKinematicsFactor.begin();
iter != collector_ForwardKinematicsFactor.end(); ) {
delete *iter;
collector_ForwardKinematicsFactor.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ns1ClassA::iterator iter = collector_ns1ClassA.begin(); { for(Collector_ns1ClassA::iterator iter = collector_ns1ClassA.begin();
iter != collector_ns1ClassA.end(); ) { iter != collector_ns1ClassA.end(); ) {
delete *iter; delete *iter;
@ -219,6 +78,7 @@ void _deleteAllObjects()
collector_gtsamValues.erase(iter++); collector_gtsamValues.erase(iter++);
anyDeleted = true; anyDeleted = true;
} } } }
if(anyDeleted) if(anyDeleted)
cout << cout <<
"WARNING: Wrap modules with variables in the workspace have been reloaded due to\n" "WARNING: Wrap modules with variables in the workspace have been reloaded due to\n"
@ -231,10 +91,8 @@ void _namespaces_RTTIRegister() {
const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_namespaces_rttiRegistry_created"); const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_namespaces_rttiRegistry_created");
if(!alreadyCreated) { if(!alreadyCreated) {
std::map<std::string, std::string> types; std::map<std::string, std::string> types;
types.insert(std::make_pair(typeid(MyBase).name(), "MyBase"));
types.insert(std::make_pair(typeid(MyTemplatePoint2).name(), "MyTemplatePoint2"));
types.insert(std::make_pair(typeid(MyTemplateMatrix).name(), "MyTemplateMatrix"));
types.insert(std::make_pair(typeid(ForwardKinematicsFactor).name(), "ForwardKinematicsFactor"));
mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry"); mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry");
if(!registry) if(!registry)
@ -242,18 +100,21 @@ void _namespaces_RTTIRegister() {
typedef std::pair<std::string, std::string> StringPair; typedef std::pair<std::string, std::string> StringPair;
for(const StringPair& rtti_matlab: types) { for(const StringPair& rtti_matlab: types) {
int fieldId = mxAddField(registry, rtti_matlab.first.c_str()); int fieldId = mxAddField(registry, rtti_matlab.first.c_str());
if(fieldId < 0) if(fieldId < 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str()); mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str());
mxSetFieldByNumber(registry, 0, fieldId, matlabName); mxSetFieldByNumber(registry, 0, fieldId, matlabName);
} }
if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(registry); mxDestroyArray(registry);
mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL); mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL);
if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(newAlreadyCreated); mxDestroyArray(newAlreadyCreated);
} }
} }

View File

@ -5,78 +5,11 @@
#include <boost/archive/text_oarchive.hpp> #include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp> #include <boost/serialization/export.hpp>
#include <folder/path/to/Test.h>
#include <gtsam/geometry/Cal3Bundler.h> #include <gtsam/geometry/Cal3Bundler.h>
#include <gtsam/geometry/Point2.h>
#include <gtsam/geometry/Point3.h>
#include <gtsam/nonlinear/Values.h>
#include <path/to/ns1.h>
#include <path/to/ns1/ClassB.h>
#include <path/to/ns2.h>
#include <path/to/ns2/ClassA.h>
#include <path/to/ns3.h>
typedef Fun<double> FunDouble;
typedef PrimitiveRef<double> PrimitiveRefDouble;
typedef MyVector<3> MyVector3;
typedef MyVector<12> MyVector12;
typedef MultipleTemplates<int, double> MultipleTemplatesIntDouble;
typedef MultipleTemplates<int, float> MultipleTemplatesIntFloat;
typedef MyFactor<gtsam::Pose2, gtsam::Matrix> MyFactorPosePoint2;
typedef MyTemplate<gtsam::Point2> MyTemplatePoint2;
typedef MyTemplate<gtsam::Matrix> MyTemplateMatrix;
typedef gtsam::PinholeCamera<gtsam::Cal3Bundler> PinholeCameraCal3Bundler; typedef gtsam::PinholeCamera<gtsam::Cal3Bundler> PinholeCameraCal3Bundler;
typedef gtsam::GeneralSFMFactor<gtsam::PinholeCamera<gtsam::Cal3Bundler>, gtsam::Point3> GeneralSFMFactorCal3Bundler; typedef gtsam::GeneralSFMFactor<gtsam::PinholeCamera<gtsam::Cal3Bundler>, gtsam::Point3> GeneralSFMFactorCal3Bundler;
BOOST_CLASS_EXPORT_GUID(gtsam::Point2, "gtsamPoint2");
BOOST_CLASS_EXPORT_GUID(gtsam::Point3, "gtsamPoint3");
typedef std::set<boost::shared_ptr<FunRange>*> Collector_FunRange;
static Collector_FunRange collector_FunRange;
typedef std::set<boost::shared_ptr<FunDouble>*> Collector_FunDouble;
static Collector_FunDouble collector_FunDouble;
typedef std::set<boost::shared_ptr<Test>*> Collector_Test;
static Collector_Test collector_Test;
typedef std::set<boost::shared_ptr<PrimitiveRefDouble>*> Collector_PrimitiveRefDouble;
static Collector_PrimitiveRefDouble collector_PrimitiveRefDouble;
typedef std::set<boost::shared_ptr<MyVector3>*> Collector_MyVector3;
static Collector_MyVector3 collector_MyVector3;
typedef std::set<boost::shared_ptr<MyVector12>*> Collector_MyVector12;
static Collector_MyVector12 collector_MyVector12;
typedef std::set<boost::shared_ptr<MultipleTemplatesIntDouble>*> Collector_MultipleTemplatesIntDouble;
static Collector_MultipleTemplatesIntDouble collector_MultipleTemplatesIntDouble;
typedef std::set<boost::shared_ptr<MultipleTemplatesIntFloat>*> Collector_MultipleTemplatesIntFloat;
static Collector_MultipleTemplatesIntFloat collector_MultipleTemplatesIntFloat;
typedef std::set<boost::shared_ptr<ForwardKinematics>*> Collector_ForwardKinematics;
static Collector_ForwardKinematics collector_ForwardKinematics;
typedef std::set<boost::shared_ptr<MyFactorPosePoint2>*> Collector_MyFactorPosePoint2;
static Collector_MyFactorPosePoint2 collector_MyFactorPosePoint2;
typedef std::set<boost::shared_ptr<gtsam::Point2>*> Collector_gtsamPoint2;
static Collector_gtsamPoint2 collector_gtsamPoint2;
typedef std::set<boost::shared_ptr<gtsam::Point3>*> Collector_gtsamPoint3;
static Collector_gtsamPoint3 collector_gtsamPoint3;
typedef std::set<boost::shared_ptr<MyBase>*> Collector_MyBase;
static Collector_MyBase collector_MyBase;
typedef std::set<boost::shared_ptr<MyTemplatePoint2>*> Collector_MyTemplatePoint2;
static Collector_MyTemplatePoint2 collector_MyTemplatePoint2;
typedef std::set<boost::shared_ptr<MyTemplateMatrix>*> Collector_MyTemplateMatrix;
static Collector_MyTemplateMatrix collector_MyTemplateMatrix;
typedef std::set<boost::shared_ptr<ForwardKinematicsFactor>*> Collector_ForwardKinematicsFactor;
static Collector_ForwardKinematicsFactor collector_ForwardKinematicsFactor;
typedef std::set<boost::shared_ptr<ns1::ClassA>*> Collector_ns1ClassA;
static Collector_ns1ClassA collector_ns1ClassA;
typedef std::set<boost::shared_ptr<ns1::ClassB>*> Collector_ns1ClassB;
static Collector_ns1ClassB collector_ns1ClassB;
typedef std::set<boost::shared_ptr<ns2::ClassA>*> Collector_ns2ClassA;
static Collector_ns2ClassA collector_ns2ClassA;
typedef std::set<boost::shared_ptr<ns2::ns3::ClassB>*> Collector_ns2ns3ClassB;
static Collector_ns2ns3ClassB collector_ns2ns3ClassB;
typedef std::set<boost::shared_ptr<ns2::ClassC>*> Collector_ns2ClassC;
static Collector_ns2ClassC collector_ns2ClassC;
typedef std::set<boost::shared_ptr<ClassD>*> Collector_ClassD;
static Collector_ClassD collector_ClassD;
typedef std::set<boost::shared_ptr<gtsam::Values>*> Collector_gtsamValues;
static Collector_gtsamValues collector_gtsamValues;
typedef std::set<boost::shared_ptr<gtsam::NonlinearFactorGraph>*> Collector_gtsamNonlinearFactorGraph; typedef std::set<boost::shared_ptr<gtsam::NonlinearFactorGraph>*> Collector_gtsamNonlinearFactorGraph;
static Collector_gtsamNonlinearFactorGraph collector_gtsamNonlinearFactorGraph; static Collector_gtsamNonlinearFactorGraph collector_gtsamNonlinearFactorGraph;
typedef std::set<boost::shared_ptr<gtsam::SfmTrack>*> Collector_gtsamSfmTrack; typedef std::set<boost::shared_ptr<gtsam::SfmTrack>*> Collector_gtsamSfmTrack;
@ -86,150 +19,13 @@ static Collector_gtsamPinholeCameraCal3Bundler collector_gtsamPinholeCameraCal3B
typedef std::set<boost::shared_ptr<GeneralSFMFactorCal3Bundler>*> Collector_gtsamGeneralSFMFactorCal3Bundler; typedef std::set<boost::shared_ptr<GeneralSFMFactorCal3Bundler>*> Collector_gtsamGeneralSFMFactorCal3Bundler;
static Collector_gtsamGeneralSFMFactorCal3Bundler collector_gtsamGeneralSFMFactorCal3Bundler; static Collector_gtsamGeneralSFMFactorCal3Bundler collector_gtsamGeneralSFMFactorCal3Bundler;
void _deleteAllObjects() void _deleteAllObjects()
{ {
mstream mout; mstream mout;
std::streambuf *outbuf = std::cout.rdbuf(&mout); std::streambuf *outbuf = std::cout.rdbuf(&mout);
bool anyDeleted = false; bool anyDeleted = false;
{ for(Collector_FunRange::iterator iter = collector_FunRange.begin();
iter != collector_FunRange.end(); ) {
delete *iter;
collector_FunRange.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_FunDouble::iterator iter = collector_FunDouble.begin();
iter != collector_FunDouble.end(); ) {
delete *iter;
collector_FunDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_Test::iterator iter = collector_Test.begin();
iter != collector_Test.end(); ) {
delete *iter;
collector_Test.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_PrimitiveRefDouble::iterator iter = collector_PrimitiveRefDouble.begin();
iter != collector_PrimitiveRefDouble.end(); ) {
delete *iter;
collector_PrimitiveRefDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyVector3::iterator iter = collector_MyVector3.begin();
iter != collector_MyVector3.end(); ) {
delete *iter;
collector_MyVector3.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyVector12::iterator iter = collector_MyVector12.begin();
iter != collector_MyVector12.end(); ) {
delete *iter;
collector_MyVector12.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MultipleTemplatesIntDouble::iterator iter = collector_MultipleTemplatesIntDouble.begin();
iter != collector_MultipleTemplatesIntDouble.end(); ) {
delete *iter;
collector_MultipleTemplatesIntDouble.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MultipleTemplatesIntFloat::iterator iter = collector_MultipleTemplatesIntFloat.begin();
iter != collector_MultipleTemplatesIntFloat.end(); ) {
delete *iter;
collector_MultipleTemplatesIntFloat.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ForwardKinematics::iterator iter = collector_ForwardKinematics.begin();
iter != collector_ForwardKinematics.end(); ) {
delete *iter;
collector_ForwardKinematics.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyFactorPosePoint2::iterator iter = collector_MyFactorPosePoint2.begin();
iter != collector_MyFactorPosePoint2.end(); ) {
delete *iter;
collector_MyFactorPosePoint2.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamPoint2::iterator iter = collector_gtsamPoint2.begin();
iter != collector_gtsamPoint2.end(); ) {
delete *iter;
collector_gtsamPoint2.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamPoint3::iterator iter = collector_gtsamPoint3.begin();
iter != collector_gtsamPoint3.end(); ) {
delete *iter;
collector_gtsamPoint3.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyBase::iterator iter = collector_MyBase.begin();
iter != collector_MyBase.end(); ) {
delete *iter;
collector_MyBase.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyTemplatePoint2::iterator iter = collector_MyTemplatePoint2.begin();
iter != collector_MyTemplatePoint2.end(); ) {
delete *iter;
collector_MyTemplatePoint2.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_MyTemplateMatrix::iterator iter = collector_MyTemplateMatrix.begin();
iter != collector_MyTemplateMatrix.end(); ) {
delete *iter;
collector_MyTemplateMatrix.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ForwardKinematicsFactor::iterator iter = collector_ForwardKinematicsFactor.begin();
iter != collector_ForwardKinematicsFactor.end(); ) {
delete *iter;
collector_ForwardKinematicsFactor.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ns1ClassA::iterator iter = collector_ns1ClassA.begin();
iter != collector_ns1ClassA.end(); ) {
delete *iter;
collector_ns1ClassA.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ns1ClassB::iterator iter = collector_ns1ClassB.begin();
iter != collector_ns1ClassB.end(); ) {
delete *iter;
collector_ns1ClassB.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ns2ClassA::iterator iter = collector_ns2ClassA.begin();
iter != collector_ns2ClassA.end(); ) {
delete *iter;
collector_ns2ClassA.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ns2ns3ClassB::iterator iter = collector_ns2ns3ClassB.begin();
iter != collector_ns2ns3ClassB.end(); ) {
delete *iter;
collector_ns2ns3ClassB.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ns2ClassC::iterator iter = collector_ns2ClassC.begin();
iter != collector_ns2ClassC.end(); ) {
delete *iter;
collector_ns2ClassC.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_ClassD::iterator iter = collector_ClassD.begin();
iter != collector_ClassD.end(); ) {
delete *iter;
collector_ClassD.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamValues::iterator iter = collector_gtsamValues.begin();
iter != collector_gtsamValues.end(); ) {
delete *iter;
collector_gtsamValues.erase(iter++);
anyDeleted = true;
} }
{ for(Collector_gtsamNonlinearFactorGraph::iterator iter = collector_gtsamNonlinearFactorGraph.begin(); { for(Collector_gtsamNonlinearFactorGraph::iterator iter = collector_gtsamNonlinearFactorGraph.begin();
iter != collector_gtsamNonlinearFactorGraph.end(); ) { iter != collector_gtsamNonlinearFactorGraph.end(); ) {
delete *iter; delete *iter;
@ -254,6 +50,7 @@ void _deleteAllObjects()
collector_gtsamGeneralSFMFactorCal3Bundler.erase(iter++); collector_gtsamGeneralSFMFactorCal3Bundler.erase(iter++);
anyDeleted = true; anyDeleted = true;
} } } }
if(anyDeleted) if(anyDeleted)
cout << cout <<
"WARNING: Wrap modules with variables in the workspace have been reloaded due to\n" "WARNING: Wrap modules with variables in the workspace have been reloaded due to\n"
@ -266,10 +63,8 @@ void _special_cases_RTTIRegister() {
const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_special_cases_rttiRegistry_created"); const mxArray *alreadyCreated = mexGetVariablePtr("global", "gtsam_special_cases_rttiRegistry_created");
if(!alreadyCreated) { if(!alreadyCreated) {
std::map<std::string, std::string> types; std::map<std::string, std::string> types;
types.insert(std::make_pair(typeid(MyBase).name(), "MyBase"));
types.insert(std::make_pair(typeid(MyTemplatePoint2).name(), "MyTemplatePoint2"));
types.insert(std::make_pair(typeid(MyTemplateMatrix).name(), "MyTemplateMatrix"));
types.insert(std::make_pair(typeid(ForwardKinematicsFactor).name(), "ForwardKinematicsFactor"));
mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry"); mxArray *registry = mexGetVariable("global", "gtsamwrap_rttiRegistry");
if(!registry) if(!registry)
@ -277,18 +72,21 @@ void _special_cases_RTTIRegister() {
typedef std::pair<std::string, std::string> StringPair; typedef std::pair<std::string, std::string> StringPair;
for(const StringPair& rtti_matlab: types) { for(const StringPair& rtti_matlab: types) {
int fieldId = mxAddField(registry, rtti_matlab.first.c_str()); int fieldId = mxAddField(registry, rtti_matlab.first.c_str());
if(fieldId < 0) if(fieldId < 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str()); mxArray *matlabName = mxCreateString(rtti_matlab.second.c_str());
mxSetFieldByNumber(registry, 0, fieldId, matlabName); mxSetFieldByNumber(registry, 0, fieldId, matlabName);
} }
if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) if(mexPutVariable("global", "gtsamwrap_rttiRegistry", registry) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(registry); mxDestroyArray(registry);
mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL); mxArray *newAlreadyCreated = mxCreateNumericMatrix(0, 0, mxINT8_CLASS, mxREAL);
if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) if(mexPutVariable("global", "gtsam_geometry_rttiRegistry_created", newAlreadyCreated) != 0) {
mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly"); mexErrMsgTxt("gtsam wrap: Error indexing RTTI types, inheritance will not work correctly");
}
mxDestroyArray(newAlreadyCreated); mxDestroyArray(newAlreadyCreated);
} }
} }

11
tests/fixtures/part1.i vendored Normal file
View File

@ -0,0 +1,11 @@
// First file to test for multi-file support.
namespace gtsam {
class Class1 {
Class1();
};
class Class2 {
Class2();
};
} // namespace gtsam

7
tests/fixtures/part2.i vendored Normal file
View File

@ -0,0 +1,7 @@
// Second file to test for multi-file support.
namespace gtsam {
class ClassA {
ClassA();
};
} // namespace gtsam

View File

@ -22,73 +22,31 @@ class TestWrap(unittest.TestCase):
""" """
Test the Matlab wrapper Test the Matlab wrapper
""" """
TEST_DIR = osp.dirname(osp.realpath(__file__)) def setUp(self) -> None:
INTERFACE_DIR = osp.join(TEST_DIR, "fixtures") super().setUp()
MATLAB_TEST_DIR = osp.join(TEST_DIR, "expected", "matlab")
MATLAB_ACTUAL_DIR = osp.join(TEST_DIR, "actual", "matlab")
# Create the `actual/matlab` directory # Set up all the directories
os.makedirs(MATLAB_ACTUAL_DIR, exist_ok=True) self.TEST_DIR = osp.dirname(osp.realpath(__file__))
self.INTERFACE_DIR = osp.join(self.TEST_DIR, "fixtures")
self.MATLAB_TEST_DIR = osp.join(self.TEST_DIR, "expected", "matlab")
self.MATLAB_ACTUAL_DIR = osp.join(self.TEST_DIR, "actual", "matlab")
# set the log level to INFO by default if not osp.exists(self.MATLAB_ACTUAL_DIR):
logger.remove() # remove the default sink os.mkdir(self.MATLAB_ACTUAL_DIR)
logger.add(sys.stderr, format="{time} {level} {message}", level="INFO")
def generate_content(self, cc_content, path=MATLAB_ACTUAL_DIR): # Generate the matlab.h file if it does not exist
"""Generate files and folders from matlab wrapper content. template_file = osp.join(self.TEST_DIR, "..", "gtwrap",
"matlab_wrapper", "matlab_wrapper.tpl")
if not osp.exists(template_file):
with open(template_file, 'w') as tpl:
tpl.write("#include <gtwrap/matlab.h>\n#include <map>\n")
Keyword arguments: # Create the `actual/matlab` directory
cc_content -- the content to generate formatted as os.makedirs(self.MATLAB_ACTUAL_DIR, exist_ok=True)
(file_name, file_content) or
(folder_name, [(file_name, file_content)])
path -- the path to the files parent folder within the main folder
"""
for c in cc_content:
if isinstance(c, list):
if len(c) == 0:
continue
logger.debug("c object: {}".format(c[0][0]))
path_to_folder = osp.join(path, c[0][0])
if not osp.isdir(path_to_folder): # set the log level to INFO by default
try: logger.remove() # remove the default sink
os.makedirs(path_to_folder, exist_ok=True) logger.add(sys.stderr, format="{time} {level} {message}", level="INFO")
except OSError:
pass
for sub_content in c:
logger.debug("sub object: {}".format(sub_content[1][0][0]))
self.generate_content(sub_content[1], path_to_folder)
elif isinstance(c[1], list):
path_to_folder = osp.join(path, c[0])
logger.debug(
"[generate_content_global]: {}".format(path_to_folder))
if not osp.isdir(path_to_folder):
try:
os.makedirs(path_to_folder, exist_ok=True)
except OSError:
pass
for sub_content in c[1]:
path_to_file = osp.join(path_to_folder, sub_content[0])
logger.debug(
"[generate_global_method]: {}".format(path_to_file))
with open(path_to_file, 'w') as f:
f.write(sub_content[1])
else:
path_to_file = osp.join(path, c[0])
logger.debug("[generate_content]: {}".format(path_to_file))
if not osp.isdir(path_to_file):
try:
os.mkdir(path)
except OSError:
pass
with open(path_to_file, 'w') as f:
f.write(c[1])
def compare_and_diff(self, file): def compare_and_diff(self, file):
""" """
@ -109,11 +67,7 @@ class TestWrap(unittest.TestCase):
python3 wrap/matlab_wrapper.py --src wrap/tests/geometry.h python3 wrap/matlab_wrapper.py --src wrap/tests/geometry.h
--module_name geometry --out wrap/tests/actual-matlab --module_name geometry --out wrap/tests/actual-matlab
""" """
with open(osp.join(self.INTERFACE_DIR, 'geometry.i'), 'r') as f: file = osp.join(self.INTERFACE_DIR, 'geometry.i')
content = f.read()
if not osp.exists(self.MATLAB_ACTUAL_DIR):
os.mkdir(self.MATLAB_ACTUAL_DIR)
# Create MATLAB wrapper instance # Create MATLAB wrapper instance
wrapper = MatlabWrapper( wrapper = MatlabWrapper(
@ -122,24 +76,18 @@ class TestWrap(unittest.TestCase):
ignore_classes=[''], ignore_classes=[''],
) )
cc_content = wrapper.wrap(content) wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
self.generate_content(cc_content)
self.assertTrue(osp.isdir(osp.join(self.MATLAB_ACTUAL_DIR, '+gtsam')))
files = ['+gtsam/Point2.m', '+gtsam/Point3.m', 'geometry_wrapper.cpp'] files = ['+gtsam/Point2.m', '+gtsam/Point3.m', 'geometry_wrapper.cpp']
self.assertTrue(osp.isdir(osp.join(self.MATLAB_ACTUAL_DIR, '+gtsam')))
for file in files: for file in files:
self.compare_and_diff(file) self.compare_and_diff(file)
def test_functions(self): def test_functions(self):
"""Test interface file with function info.""" """Test interface file with function info."""
with open(osp.join(self.INTERFACE_DIR, 'functions.i'), 'r') as f: file = osp.join(self.INTERFACE_DIR, 'functions.i')
content = f.read()
if not osp.exists(self.MATLAB_ACTUAL_DIR):
os.mkdir(self.MATLAB_ACTUAL_DIR)
wrapper = MatlabWrapper( wrapper = MatlabWrapper(
module_name='functions', module_name='functions',
@ -147,9 +95,7 @@ class TestWrap(unittest.TestCase):
ignore_classes=[''], ignore_classes=[''],
) )
cc_content = wrapper.wrap(content) wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
self.generate_content(cc_content)
files = [ files = [
'functions_wrapper.cpp', 'aGlobalFunction.m', 'load2D.m', 'functions_wrapper.cpp', 'aGlobalFunction.m', 'load2D.m',
@ -163,11 +109,7 @@ class TestWrap(unittest.TestCase):
def test_class(self): def test_class(self):
"""Test interface file with only class info.""" """Test interface file with only class info."""
with open(osp.join(self.INTERFACE_DIR, 'class.i'), 'r') as f: file = osp.join(self.INTERFACE_DIR, 'class.i')
content = f.read()
if not osp.exists(self.MATLAB_ACTUAL_DIR):
os.mkdir(self.MATLAB_ACTUAL_DIR)
wrapper = MatlabWrapper( wrapper = MatlabWrapper(
module_name='class', module_name='class',
@ -175,9 +117,7 @@ class TestWrap(unittest.TestCase):
ignore_classes=[''], ignore_classes=[''],
) )
cc_content = wrapper.wrap(content) wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
self.generate_content(cc_content)
files = [ files = [
'class_wrapper.cpp', 'FunDouble.m', 'FunRange.m', 'class_wrapper.cpp', 'FunDouble.m', 'FunRange.m',
@ -191,21 +131,14 @@ class TestWrap(unittest.TestCase):
def test_inheritance(self): def test_inheritance(self):
"""Test interface file with class inheritance definitions.""" """Test interface file with class inheritance definitions."""
with open(osp.join(self.INTERFACE_DIR, 'inheritance.i'), 'r') as f: file = osp.join(self.INTERFACE_DIR, 'inheritance.i')
content = f.read()
if not osp.exists(self.MATLAB_ACTUAL_DIR):
os.mkdir(self.MATLAB_ACTUAL_DIR)
wrapper = MatlabWrapper( wrapper = MatlabWrapper(
module_name='inheritance', module_name='inheritance',
top_module_namespace=['gtsam'], top_module_namespace=['gtsam'],
ignore_classes=[''], ignore_classes=[''],
) )
wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
cc_content = wrapper.wrap(content)
self.generate_content(cc_content)
files = [ files = [
'inheritance_wrapper.cpp', 'MyBase.m', 'MyTemplateMatrix.m', 'inheritance_wrapper.cpp', 'MyBase.m', 'MyTemplateMatrix.m',
@ -219,11 +152,7 @@ class TestWrap(unittest.TestCase):
""" """
Test interface file with full namespace definition. Test interface file with full namespace definition.
""" """
with open(osp.join(self.INTERFACE_DIR, 'namespaces.i'), 'r') as f: file = osp.join(self.INTERFACE_DIR, 'namespaces.i')
content = f.read()
if not osp.exists(self.MATLAB_ACTUAL_DIR):
os.mkdir(self.MATLAB_ACTUAL_DIR)
wrapper = MatlabWrapper( wrapper = MatlabWrapper(
module_name='namespaces', module_name='namespaces',
@ -231,9 +160,7 @@ class TestWrap(unittest.TestCase):
ignore_classes=[''], ignore_classes=[''],
) )
cc_content = wrapper.wrap(content) wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
self.generate_content(cc_content)
files = [ files = [
'namespaces_wrapper.cpp', '+ns1/aGlobalFunction.m', 'namespaces_wrapper.cpp', '+ns1/aGlobalFunction.m',
@ -249,21 +176,14 @@ class TestWrap(unittest.TestCase):
""" """
Tests for some unique, non-trivial features. Tests for some unique, non-trivial features.
""" """
with open(osp.join(self.INTERFACE_DIR, 'special_cases.i'), 'r') as f: file = osp.join(self.INTERFACE_DIR, 'special_cases.i')
content = f.read()
if not osp.exists(self.MATLAB_ACTUAL_DIR):
os.mkdir(self.MATLAB_ACTUAL_DIR)
wrapper = MatlabWrapper( wrapper = MatlabWrapper(
module_name='special_cases', module_name='special_cases',
top_module_namespace=['gtsam'], top_module_namespace=['gtsam'],
ignore_classes=[''], ignore_classes=[''],
) )
wrapper.wrap([file], path=self.MATLAB_ACTUAL_DIR)
cc_content = wrapper.wrap(content)
self.generate_content(cc_content)
files = [ files = [
'special_cases_wrapper.cpp', 'special_cases_wrapper.cpp',
@ -274,6 +194,31 @@ class TestWrap(unittest.TestCase):
for file in files: for file in files:
self.compare_and_diff(file) self.compare_and_diff(file)
def test_multiple_files(self):
"""
Test for when multiple interface files are specified.
"""
file1 = osp.join(self.INTERFACE_DIR, 'part1.i')
file2 = osp.join(self.INTERFACE_DIR, 'part2.i')
wrapper = MatlabWrapper(
module_name='multiple_files',
top_module_namespace=['gtsam'],
ignore_classes=[''],
)
wrapper.wrap([file1, file2], path=self.MATLAB_ACTUAL_DIR)
files = [
'multiple_files_wrapper.cpp',
'+gtsam/Class1.m',
'+gtsam/Class2.m',
'+gtsam/ClassA.m',
]
for file in files:
self.compare_and_diff(file)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -31,9 +31,9 @@ class TestWrap(unittest.TestCase):
# Create the `actual/python` directory # Create the `actual/python` directory
os.makedirs(PYTHON_ACTUAL_DIR, exist_ok=True) os.makedirs(PYTHON_ACTUAL_DIR, exist_ok=True)
def wrap_content(self, content, module_name, output_dir): def wrap_content(self, sources, module_name, output_dir):
""" """
Common function to wrap content. Common function to wrap content in `sources`.
""" """
with open(osp.join(self.TEST_DIR, with open(osp.join(self.TEST_DIR,
"pybind_wrapper.tpl")) as template_file: "pybind_wrapper.tpl")) as template_file:
@ -46,15 +46,12 @@ class TestWrap(unittest.TestCase):
ignore_classes=[''], ignore_classes=[''],
module_template=module_template) module_template=module_template)
cc_content = wrapper.wrap(content)
output = osp.join(self.TEST_DIR, output_dir, module_name + ".cpp") output = osp.join(self.TEST_DIR, output_dir, module_name + ".cpp")
if not osp.exists(osp.join(self.TEST_DIR, output_dir)): if not osp.exists(osp.join(self.TEST_DIR, output_dir)):
os.mkdir(osp.join(self.TEST_DIR, output_dir)) os.mkdir(osp.join(self.TEST_DIR, output_dir))
with open(output, 'w') as f: wrapper.wrap(sources, output)
f.write(cc_content)
return output return output
@ -76,39 +73,32 @@ class TestWrap(unittest.TestCase):
python3 ../pybind_wrapper.py --src geometry.h --module_name python3 ../pybind_wrapper.py --src geometry.h --module_name
geometry_py --out output/geometry_py.cc geometry_py --out output/geometry_py.cc
""" """
with open(osp.join(self.INTERFACE_DIR, 'geometry.i'), 'r') as f: source = osp.join(self.INTERFACE_DIR, 'geometry.i')
content = f.read() output = self.wrap_content([source], 'geometry_py',
output = self.wrap_content(content, 'geometry_py',
self.PYTHON_ACTUAL_DIR) self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('geometry_pybind.cpp', output) self.compare_and_diff('geometry_pybind.cpp', output)
def test_functions(self): def test_functions(self):
"""Test interface file with function info.""" """Test interface file with function info."""
with open(osp.join(self.INTERFACE_DIR, 'functions.i'), 'r') as f: source = osp.join(self.INTERFACE_DIR, 'functions.i')
content = f.read() output = self.wrap_content([source], 'functions_py',
output = self.wrap_content(content, 'functions_py',
self.PYTHON_ACTUAL_DIR) self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('functions_pybind.cpp', output) self.compare_and_diff('functions_pybind.cpp', output)
def test_class(self): def test_class(self):
"""Test interface file with only class info.""" """Test interface file with only class info."""
with open(osp.join(self.INTERFACE_DIR, 'class.i'), 'r') as f: source = osp.join(self.INTERFACE_DIR, 'class.i')
content = f.read() output = self.wrap_content([source], 'class_py',
self.PYTHON_ACTUAL_DIR)
output = self.wrap_content(content, 'class_py', self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('class_pybind.cpp', output) self.compare_and_diff('class_pybind.cpp', output)
def test_inheritance(self): def test_inheritance(self):
"""Test interface file with class inheritance definitions.""" """Test interface file with class inheritance definitions."""
with open(osp.join(self.INTERFACE_DIR, 'inheritance.i'), 'r') as f: source = osp.join(self.INTERFACE_DIR, 'inheritance.i')
content = f.read() output = self.wrap_content([source], 'inheritance_py',
output = self.wrap_content(content, 'inheritance_py',
self.PYTHON_ACTUAL_DIR) self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('inheritance_pybind.cpp', output) self.compare_and_diff('inheritance_pybind.cpp', output)
@ -119,10 +109,8 @@ class TestWrap(unittest.TestCase):
python3 ../pybind_wrapper.py --src namespaces.i --module_name python3 ../pybind_wrapper.py --src namespaces.i --module_name
namespaces_py --out output/namespaces_py.cpp namespaces_py --out output/namespaces_py.cpp
""" """
with open(osp.join(self.INTERFACE_DIR, 'namespaces.i'), 'r') as f: source = osp.join(self.INTERFACE_DIR, 'namespaces.i')
content = f.read() output = self.wrap_content([source], 'namespaces_py',
output = self.wrap_content(content, 'namespaces_py',
self.PYTHON_ACTUAL_DIR) self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('namespaces_pybind.cpp', output) self.compare_and_diff('namespaces_pybind.cpp', output)
@ -131,10 +119,8 @@ class TestWrap(unittest.TestCase):
""" """
Tests for operator overloading. Tests for operator overloading.
""" """
with open(osp.join(self.INTERFACE_DIR, 'operator.i'), 'r') as f: source = osp.join(self.INTERFACE_DIR, 'operator.i')
content = f.read() output = self.wrap_content([source], 'operator_py',
output = self.wrap_content(content, 'operator_py',
self.PYTHON_ACTUAL_DIR) self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('operator_pybind.cpp', output) self.compare_and_diff('operator_pybind.cpp', output)
@ -143,10 +129,8 @@ class TestWrap(unittest.TestCase):
""" """
Tests for some unique, non-trivial features. Tests for some unique, non-trivial features.
""" """
with open(osp.join(self.INTERFACE_DIR, 'special_cases.i'), 'r') as f: source = osp.join(self.INTERFACE_DIR, 'special_cases.i')
content = f.read() output = self.wrap_content([source], 'special_cases_py',
output = self.wrap_content(content, 'special_cases_py',
self.PYTHON_ACTUAL_DIR) self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('special_cases_pybind.cpp', output) self.compare_and_diff('special_cases_pybind.cpp', output)
@ -155,10 +139,8 @@ class TestWrap(unittest.TestCase):
""" """
Test if enum generation is correct. Test if enum generation is correct.
""" """
with open(osp.join(self.INTERFACE_DIR, 'enum.i'), 'r') as f: source = osp.join(self.INTERFACE_DIR, 'enum.i')
content = f.read() output = self.wrap_content([source], 'enum_py', self.PYTHON_ACTUAL_DIR)
output = self.wrap_content(content, 'enum_py', self.PYTHON_ACTUAL_DIR)
self.compare_and_diff('enum_pybind.cpp', output) self.compare_and_diff('enum_pybind.cpp', output)