Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions DOCS.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the
- Methods
- Constness has no effect.
- Specify by-value (not reference) return types, even if C++ method returns reference.
- MATLAB maps a disengaged `std::optional<T>` to `[]` and an engaged
optional to the normal wrapped representation of `T`.
`std::optional<std::pair<T, U>>` follows the existing pair convention:
two MATLAB outputs, both `[]` when the optional is disengaged.
- Must start with a letter (upper or lowercase).
- Overloads are supported.

Expand All @@ -39,6 +43,10 @@ The python wrapper supports keyword arguments for functions/methods. Hence, the
- C/C++ basic types: `string`, `bool`, `size_t`, `size_t`, `double`, `char`, `unsigned char`.
- Any class with which be copied with `std::make_shared()` (except Eigen).
- `std::shared_ptr` of any object type (except Eigen).
- For MATLAB, `std::optional<T>` accepts `[]` for `std::nullopt` or the
normal MATLAB representation of `T` for an engaged value. Consequently,
an engaged optional containing an empty MATLAB array cannot be
distinguished from `std::nullopt`.

- Properties or Variables
- You can specify class variables in the interface file as long as they are in the `public` scope, e.g.
Expand Down
38 changes: 37 additions & 1 deletion gtwrap/matlab_wrapper/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,31 @@ def is_eigen_ref(self, arg_type) -> bool:
and len(arg_type.template_params) == 1
and arg_type.template_params[0].typename.name
in self.eigen_ref_types)


@staticmethod
def is_optional(arg_type: parser.Type) -> bool:
"""Check whether ``arg_type`` is a ``std::optional<T>``."""
return (isinstance(arg_type, parser.TemplatedType)
and arg_type.typename.qualified_name() == 'std::optional'
and len(arg_type.template_params) == 1)

def optional_value_type(self, arg_type: parser.Type) -> parser.Type:
"""Return ``T`` from ``std::optional<T>``.

Raises:
ValueError: If ``arg_type`` is not a well-formed ``std::optional``.
"""
if not self.is_optional(arg_type):
raise ValueError(f'Expected std::optional<T>, got {arg_type}')
return arg_type.template_params[0]

@staticmethod
def is_pair(arg_type: parser.Type) -> bool:
"""Check whether ``arg_type`` is a ``std::pair<T, U>``."""
return (isinstance(arg_type, parser.TemplatedType)
and arg_type.typename.qualified_name() in ('pair', 'std::pair')
and len(arg_type.template_params) == 2)

def is_class_enum(self, arg_type: parser.Type, class_: parser.Class):
"""Check if arg_type is an enum in the class `class_`."""
if class_:
Expand Down Expand Up @@ -213,6 +237,18 @@ def _format_return_type(self,
"""
return_wrap = ''

optional_pair_types = self._optional_pair_types(return_type.type1)
if optional_pair_types:
return 'optional<pair< {type1}, {type2} >>'.format(
type1=self._format_type_name(
optional_pair_types[0].typename,
separator=separator,
include_namespace=include_namespace),
type2=self._format_type_name(
optional_pair_types[1].typename,
separator=separator,
include_namespace=include_namespace))

if self._return_count(return_type) == 1:
return_wrap = self._format_type_name(
return_type.type1.typename,
Expand Down
Loading
Loading