wrapper.py
Go to the documentation of this file.
1 """
2 Code to use the parsed results and convert it to a format
3 that Matlab's MEX compiler can use.
4 """
5 
6 # pylint: disable=too-many-lines, no-self-use, too-many-arguments, too-many-branches, too-many-statements, consider-using-f-string, unspecified-encoding
7 
8 import copy
9 import os
10 import os.path as osp
11 import textwrap
12 from functools import partial, reduce
13 from typing import Dict, Iterable, List, Union
14 
15 import gtwrap.interface_parser as parser
16 import gtwrap.template_instantiator as instantiator
17 from gtwrap.interface_parser.function import ArgumentList
18 from gtwrap.matlab_wrapper.mixins import CheckMixin, FormatMixin
19 from gtwrap.matlab_wrapper.templates import WrapperTemplate
20 from gtwrap.template_instantiator.classes import InstantiatedClass
21 
22 
24  """ Wrap the given C++ code into Matlab.
25 
26  Attributes
27  module: the C++ module being wrapped
28  module_name: name of the C++ module being wrapped
29  top_module_namespace: C++ namespace for the top module (default '')
30  ignore_classes: A list of classes to ignore (default [])
31  """
32 
33  def __init__(self,
34  module_name,
35  top_module_namespace='',
36  ignore_classes=(),
37  use_boost_serialization=False):
38  super().__init__()
39 
40  self.module_name = module_name
41  self.top_module_namespace = top_module_namespace
42  self.ignore_classes = ignore_classes
43  self.verbose = False
44  self.use_boost_serialization = use_boost_serialization
45 
46  # Map the data type to its Matlab class.
47  # Found in Argument.cpp in old wrapper
48  self.data_type = {
49  'string': 'char',
50  'char': 'char',
51  'unsigned char': 'unsigned char',
52  'Vector': 'double',
53  'Matrix': 'double',
54  'int': 'numeric',
55  'size_t': 'numeric',
56  'bool': 'logical'
57  }
58  # Map the data type into the type used in Matlab methods.
59  # Found in matlab.h in old wrapper
60  self.data_type_param = {
61  'string': 'char',
62  'char': 'char',
63  'unsigned char': 'unsigned char',
64  'size_t': 'int',
65  'int': 'int',
66  'double': 'double',
67  'Point2': 'double',
68  'Point3': 'double',
69  'Vector': 'double',
70  'Matrix': 'double',
71  'bool': 'bool'
72  }
73  # The amount of times the wrapper has created a call to geometry_wrapper
74  self.wrapper_id = 0
75  # Map each wrapper id to its collector function namespace, class, type, and string format
76  self.wrapper_map: Dict = {}
77  # Set of all the includes in the namespace
78  self.includes: List[parser.Include] = []
79  # Set of all classes in the namespace
80  self.classes: List[Union[parser.Class,
81  instantiator.InstantiatedClass]] = []
82  self.classes_elems: Dict[Union[parser.Class,
83  instantiator.InstantiatedClass],
84  int] = {}
85  # Id for ordering global functions in the wrapper
86  self.global_function_id = 0
87  # Files and their content
88  self.content: List[str] = []
89 
90  # Ensure the template file is always picked up from the correct directory.
91  dir_path = osp.dirname(osp.realpath(__file__))
92  with open(osp.join(dir_path, "matlab_wrapper.tpl")) as f:
93  self.wrapper_file_headers = f.read()
94 
95  def add_class(self, instantiated_class):
96  """Add `instantiated_class` to the list of classes."""
97  if self.classes_elems.get(instantiated_class) is None:
98  self.classes_elems[instantiated_class] = 0
99  self.classes.append(instantiated_class)
100 
102  collector_function=None,
103  id_diff=0,
104  function_name: str = None):
105  """
106  Get and define wrapper ids.
107  Generates the map of id -> collector function.
108 
109  Args:
110  collector_function: tuple storing info about the wrapper function
111  (namespace, class instance, function name, function object)
112  id_diff: constant to add to the id in the map
113  function_name: Optional custom function_name.
114 
115  Returns:
116  the current wrapper id
117  """
118  if collector_function is not None:
119  is_instantiated_class = isinstance(collector_function[1],
120  instantiator.InstantiatedClass)
121 
122  if function_name is None:
123  if is_instantiated_class:
124  function_name = collector_function[0] + \
125  collector_function[1].name + '_' + collector_function[2]
126  else:
127  function_name = collector_function[1].name
128 
129  self.wrapper_map[self.wrapper_id] = (
130  collector_function[0], collector_function[1],
131  collector_function[2], function_name + '_' +
132  str(self.wrapper_id + id_diff), collector_function[3])
133 
134  self.wrapper_id += 1
135 
136  return self.wrapper_id - 1
137 
138  def _qualified_name(self, names):
139  return 'handle' if names == '' else names
140 
141  def _insert_spaces(self, x, y):
142  """Insert spaces at the beginning of each line
143 
144  Args:
145  x: the statement currently generated
146  y: the addition to add to the statement
147  """
148  return x + '\n' + ('' if y == '' else ' ') + y
149 
150  @staticmethod
151  def _expand_default_arguments(method, save_backup=True):
152  """Recursively expand all possibilities for optional default arguments.
153  We create "overload" functions with fewer arguments, but since we have to "remember" what
154  the default arguments are for later, we make a backup.
155  """
156 
157  def args_copy(args):
158  return ArgumentList([copy.copy(arg) for arg in args.list()])
159 
160  def method_copy(method):
161  method2 = copy.copy(method)
162  method2.args = args_copy(method.args)
163  method2.args.backup = method.args.backup
164  return method2
165 
166  if save_backup:
167  method.args.backup = args_copy(method.args)
168  method = method_copy(method)
169  for arg in reversed(method.args.list()):
170  if arg.default is not None:
171  arg.default = None
172  methodWithArg = method_copy(method)
173  method.args.list().remove(arg)
174  return [
175  methodWithArg,
176  *MatlabWrapper._expand_default_arguments(method,
177  save_backup=False)
178  ]
179  break
180  assert all(arg.default is None for arg in method.args.list()), \
181  'In parsing method {:}: Arguments with default values cannot appear before ones ' \
182  'without default values.'.format(method.name)
183  return [method]
184 
185  def _group_methods(self, methods):
186  """Group overloaded methods together"""
187  method_map = {}
188  method_out = []
189 
190  for method in methods:
191  method_index = method_map.get(method.name)
192 
193  if method_index is None:
194  method_map[method.name] = len(method_out)
195  method_out.append(
196  MatlabWrapper._expand_default_arguments(method))
197  else:
198  method_out[
199  method_index] += MatlabWrapper._expand_default_arguments(
200  method)
201 
202  return method_out
203 
204  def _wrap_args(self, args):
205  """Wrap an interface_parser.ArgumentList into a list of arguments.
206 
207  Returns:
208  A string representation of the arguments. For example:
209  'int x, double y'
210  """
211  arg_wrap = ''
212 
213  for i, arg in enumerate(args.list(), 1):
214  c_type = self._format_type_name(arg.ctype.typename,
215  include_namespace=False)
216 
217  arg_wrap += '{c_type} {arg_name}{comma}'.format(
218  c_type=c_type,
219  arg_name=arg.name,
220  comma='' if i == len(args.list()) else ', ')
221 
222  return arg_wrap
223 
224  def _wrap_variable_arguments(self, args, wrap_datatypes=True):
225  """ Wrap an interface_parser.ArgumentList into a statement of argument
226  checks.
227 
228  Returns:
229  A string representation of a variable arguments for an if
230  statement. For example:
231  ' && isa(varargin{1},'double') && isa(varargin{2},'numeric')'
232  """
233  var_arg_wrap = ''
234 
235  for i, arg in enumerate(args.list(), 1):
236  name = arg.ctype.typename.name
237  if name in self.not_check_type:
238  continue
239 
240  check_type = self.data_type_param.get(name)
241 
242  if self.data_type.get(check_type):
243  check_type = self.data_type[check_type]
244 
245  if check_type is None:
246  check_type = self._format_type_name(
247  arg.ctype.typename,
248  separator='.',
249  is_constructor=not wrap_datatypes)
250 
251  var_arg_wrap += " && isa(varargin{{{num}}},'{data_type}')".format(
252  num=i, data_type=check_type)
253  if name == 'Vector':
254  var_arg_wrap += ' && size(varargin{{{num}}},2)==1'.format(
255  num=i)
256  if name == 'Point2':
257  var_arg_wrap += ' && size(varargin{{{num}}},1)==2'.format(
258  num=i)
259  var_arg_wrap += ' && size(varargin{{{num}}},2)==1'.format(
260  num=i)
261  if name == 'Point3':
262  var_arg_wrap += ' && size(varargin{{{num}}},1)==3'.format(
263  num=i)
264  var_arg_wrap += ' && size(varargin{{{num}}},2)==1'.format(
265  num=i)
266 
267  return var_arg_wrap
268 
270  """ Wrap an interface_parser.ArgumentList into a list of argument
271  variables.
272 
273  Returns:
274  A string representation of a list of variable arguments.
275  For example:
276  'varargin{1}, varargin{2}, varargin{3}'
277  """
278  var_list_wrap = ''
279  first = True
280 
281  for i in range(1, len(args.list()) + 1):
282  if first:
283  var_list_wrap += 'varargin{{{}}}'.format(i)
284  first = False
285  else:
286  var_list_wrap += ', varargin{{{}}}'.format(i)
287 
288  return var_list_wrap
289 
290  def _wrap_method_check_statement(self, args: parser.ArgumentList):
291  """
292  Wrap the given arguments into either just a varargout call or a
293  call in an if statement that checks if the parameters are accurate.
294 
295  TODO Update this method so that default arguments are supported.
296  """
297  arg_id = 1
298 
299  param_count = len(args)
300  check_statement = 'if length(varargin) == {param_count}'.format(
301  param_count=param_count)
302 
303  for _, arg in enumerate(args.list()):
304  name = arg.ctype.typename.name
305 
306  if name in self.not_check_type:
307  arg_id += 1
308  continue
309 
310  check_type = self.data_type_param.get(name)
311 
312  if self.data_type.get(check_type):
313  check_type = self.data_type[check_type]
314 
315  if check_type is None:
316  check_type = self._format_type_name(arg.ctype.typename,
317  separator='.')
318 
319  check_statement += " && isa(varargin{{{id}}},'{ctype}')".format(
320  id=arg_id, ctype=check_type)
321 
322  if name == 'Vector':
323  check_statement += ' && size(varargin{{{num}}},2)==1'.format(
324  num=arg_id)
325  if name == 'Point2':
326  check_statement += ' && size(varargin{{{num}}},1)==2'.format(
327  num=arg_id)
328  check_statement += ' && size(varargin{{{num}}},2)==1'.format(
329  num=arg_id)
330  if name == 'Point3':
331  check_statement += ' && size(varargin{{{num}}},1)==3'.format(
332  num=arg_id)
333  check_statement += ' && size(varargin{{{num}}},2)==1'.format(
334  num=arg_id)
335 
336  arg_id += 1
337 
338  check_statement = check_statement \
339  if check_statement == '' \
340  else check_statement + '\n'
341 
342  return check_statement
343 
344  def _unwrap_argument(self, arg, arg_id=0, instantiated_class=None):
345  ctype_camel = self._format_type_name(arg.ctype.typename, separator='')
346  ctype_sep = self._format_type_name(arg.ctype.typename)
347 
348  if instantiated_class and \
349  self.is_enum(arg.ctype, instantiated_class):
350  enum_type = f"{arg.ctype.typename}"
351  arg_type = f"{enum_type}"
352  unwrap = f'unwrap_enum<{enum_type}>(in[{arg_id}]);'
353 
354  elif self.is_ref(arg.ctype): # and not constructor:
355  arg_type = "{ctype}&".format(ctype=ctype_sep)
356  unwrap = '*unwrap_shared_ptr< {ctype} >(in[{id}], "ptr_{ctype_camel}");'.format(
357  ctype=ctype_sep, ctype_camel=ctype_camel, id=arg_id)
358 
359  elif self.is_ptr(arg.ctype) and \
360  arg.ctype.typename.name not in self.ignore_namespace:
361 
362  arg_type = "{ctype_sep}*".format(ctype_sep=ctype_sep)
363  unwrap = 'unwrap_ptr< {ctype_sep} >(in[{id}], "ptr_{ctype}");'.format(
364  ctype_sep=ctype_sep, ctype=ctype_camel, id=arg_id)
365 
366  elif (self.is_shared_ptr(arg.ctype) or self.can_be_pointer(arg.ctype)) and \
367  arg.ctype.typename.name not in self.ignore_namespace:
368 
369  arg_type = "std::shared_ptr<{ctype_sep}>".format(
370  ctype_sep=ctype_sep)
371  unwrap = 'unwrap_shared_ptr< {ctype_sep} >(in[{id}], "ptr_{ctype}");'.format(
372  ctype_sep=ctype_sep, ctype=ctype_camel, id=arg_id)
373 
374  else:
375  arg_type = "{ctype}".format(ctype=arg.ctype.typename.name)
376  unwrap = 'unwrap< {ctype} >(in[{id}]);'.format(
377  ctype=arg.ctype.typename.name, id=arg_id)
378 
379  return arg_type, unwrap
380 
382  args,
383  arg_id=0,
384  instantiated_class=None):
385  """Format the interface_parser.Arguments.
386 
387  Examples:
388  ((a), unsigned char a = unwrap< unsigned char >(in[1]);),
389  ((a), Test& t = *unwrap_shared_ptr< Test >(in[1], "ptr_Test");),
390  ((a), std::shared_ptr<Test> p1 = unwrap_shared_ptr< Test >(in[1], "ptr_Test");)
391  """
392  body_args = ''
393 
394  for arg in args.list():
395  arg_type, unwrap = self._unwrap_argument(
396  arg, arg_id, instantiated_class=instantiated_class)
397 
398  body_args += textwrap.indent(textwrap.dedent('''\
399  {arg_type} {name} = {unwrap}
400  '''.format(arg_type=arg_type, name=arg.name,
401  unwrap=unwrap)),
402  prefix=' ')
403  arg_id += 1
404 
405  params = ''
406  explicit_arg_names = [arg.name for arg in args.list()]
407  # when returning the params list, we need to re-include the default args.
408  for arg in args.backup.list():
409  if params != '':
410  params += ','
411 
412  if (arg.default is not None) and (arg.name
413  not in explicit_arg_names):
414  params += arg.default
415  continue
416 
417  if not self.is_ref(arg.ctype) and (self.is_shared_ptr(arg.ctype) or \
418  self.is_ptr(arg.ctype) or self.can_be_pointer(arg.ctype)) and \
419  not self.is_enum(arg.ctype, instantiated_class) and \
420  arg.ctype.typename.name not in self.ignore_namespace:
421  if arg.ctype.is_shared_ptr:
422  call_type = arg.ctype.is_shared_ptr
423  else:
424  call_type = arg.ctype.is_ptr
425  if call_type == "":
426  params += "*"
427  params += arg.name
428 
429  return params, body_args
430 
431  @staticmethod
432  def _return_count(return_type):
433  """The amount of objects returned by the given
434  interface_parser.ReturnType.
435  """
436  return 1 if return_type.type2 == '' else 2
437 
438  def _wrapper_name(self):
439  """Determine the name of wrapper function."""
440  return self.module_name + '_wrapper'
441 
442  def class_serialize_comment(self, class_name, static_methods):
443  """Generate comments for serialize methods."""
444  comment_wrap = ''
445  static_methods = sorted(static_methods, key=lambda name: name.name)
446 
447  for static_method in static_methods:
448  if comment_wrap == '':
449  comment_wrap = '%-------Static Methods-------\n'
450 
451  comment_wrap += '%{name}({args}) : returns {return_type}\n'.format(
452  name=static_method.name,
453  args=self._wrap_args(static_method.args),
454  return_type=self._format_return_type(static_method.return_type,
455  include_namespace=True))
456 
457  comment_wrap += textwrap.dedent('''\
458  %
459  %-------Serialization Interface-------
460  %string_serialize() : returns string
461  %string_deserialize(string serialized) : returns {class_name}
462  %
463  ''').format(class_name=class_name)
464 
465  return comment_wrap
466 
467  def class_comment(self, instantiated_class):
468  """Generate comments for the given class in Matlab.
469 
470  Args
471  instantiated_class: the class being wrapped
472  ctors: a list of the constructors in the class
473  methods: a list of the methods in the class
474  """
475  class_name = instantiated_class.name
476  ctors = instantiated_class.ctors
477  properties = instantiated_class.properties
478  methods = instantiated_class.methods
479  static_methods = instantiated_class.static_methods
480 
481  comment = textwrap.dedent('''\
482  %class {class_name}, see Doxygen page for details
483  %at https://gtsam.org/doxygen/
484  ''').format(class_name=class_name)
485 
486  if len(ctors) != 0:
487  comment += '%\n%-------Constructors-------\n'
488 
489  # Write constructors
490  for ctor in ctors:
491  comment += '%{ctor_name}({args})\n'.format(ctor_name=ctor.name,
492  args=self._wrap_args(
493  ctor.args))
494 
495  if len(properties) != 0:
496  comment += '%\n' \
497  '%-------Properties-------\n'
498  for propty in properties:
499  comment += '%{}\n'.format(propty.name)
500 
501  if len(methods) != 0:
502  comment += '%\n' \
503  '%-------Methods-------\n'
504 
505  methods = sorted(methods, key=lambda name: name.name)
506 
507  # Write methods
508  for method in methods:
509  if method.name in self.whitelist:
510  continue
511  if method.name in self.ignore_methods:
512  continue
513 
514  comment += '%{name}({args})'.format(name=method.name,
515  args=self._wrap_args(
516  method.args))
517 
518  if method.return_type.type2 == '':
519  return_type = self._format_type_name(
520  method.return_type.type1.typename)
521  else:
522  return_type = 'pair< {type1}, {type2} >'.format(
523  type1=self._format_type_name(
524  method.return_type.type1.typename),
525  type2=self._format_type_name(
526  method.return_type.type2.typename))
527 
528  comment += ' : returns {return_type}\n'.format(
529  return_type=return_type)
530 
531  comment += '%\n'
532 
533  if len(static_methods) != 0:
534  comment += self.class_serialize_comment(class_name, static_methods)
535 
536  return comment
537 
538  def wrap_method(self, methods):
539  """
540  Wrap methods in the body of a class.
541  """
542  if not isinstance(methods, list):
543  methods = [methods]
544 
545  return ''
546 
547  def wrap_methods(self, methods, global_funcs=False, global_ns=None):
548  """
549  Wrap a sequence of methods/functions. Groups methods with the same names
550  together.
551  If global_funcs is True then output every method into its own file.
552  """
553  output = ''
554  methods = self._group_methods(methods)
555 
556  for method in methods:
557  if method in self.ignore_methods:
558  continue
559 
560  if global_funcs:
561  method_text = self.wrap_global_function(method)
562  self.content.append(("".join([
563  '+' + x + '/' for x in global_ns.full_namespaces()[1:]
564  ])[:-1], [(method[0].name + '.m', method_text)]))
565  else:
566  method_text = self.wrap_method(method)
567  output += ''
568 
569  return output
570 
571  def wrap_global_function(self, function):
572  """Wrap the given global function."""
573  if not isinstance(function, list):
574  function = [function]
575 
576  function_name = function[0].name
577 
578  # Get all combinations of parameters
579  param_wrap = ''
580 
581  for i, overload in enumerate(function):
582  param_wrap += ' if' if i == 0 else ' elseif'
583  param_wrap += ' length(varargin) == '
584 
585  if len(overload.args.list()) == 0:
586  param_wrap += '0\n'
587  else:
588  param_wrap += str(len(overload.args.list())) \
589  + self._wrap_variable_arguments(overload.args, False) + '\n'
590 
591  # Determine format of return and varargout statements
592  return_type_formatted = self._format_return_type(
593  overload.return_type, include_namespace=True, separator=".")
594  varargout = self._format_varargout(overload.return_type,
595  return_type_formatted)
596 
597  param_wrap += textwrap.indent(textwrap.dedent('''\
598  {varargout}{module_name}_wrapper({num}, varargin{{:}});
599  ''').format(varargout=varargout,
600  module_name=self.module_name,
601  num=self._update_wrapper_id(
602  collector_function=(function[0].parent.name,
603  function[i], 'global_function',
604  None))),
605  prefix=' ')
606 
607  param_wrap += textwrap.indent(textwrap.dedent('''\
608  else
609  error('Arguments do not match any overload of function {func_name}');
610  end''').format(func_name=function_name),
611  prefix=' ')
612 
613  global_function = textwrap.indent(textwrap.dedent('''\
614  function varargout = {m_method}(varargin)
615  {statements}
616  end
617  ''').format(m_method=function_name, statements=param_wrap),
618  prefix='')
619 
620  return global_function
621 
622  def wrap_class_constructors(self, namespace_name, inst_class, parent_name,
623  ctors, is_virtual):
624  """Wrap class constructor.
625 
626  Args:
627  namespace_name: the name of the namespace ('' if it does not exist)
628  inst_class: instance of the class
629  parent_name: the name of the parent class if it exists
630  ctors: the interface_parser.Constructor in the class
631  is_virtual: whether the class is part of a virtual inheritance
632  chain
633  """
634  has_parent = parent_name != ''
635  class_name = inst_class.name
636  if has_parent:
637  parent_name = self._format_type_name(parent_name, separator=".")
638  if not isinstance(ctors, Iterable):
639  ctors = [ctors]
640 
641  ctors = sum((MatlabWrapper._expand_default_arguments(ctor)
642  for ctor in ctors), [])
643 
644  methods_wrap = textwrap.indent(textwrap.dedent("""\
645  methods
646  function obj = {class_name}(varargin)
647  """).format(class_name=class_name),
648  prefix='')
649 
650  if is_virtual:
651  methods_wrap += " if (nargin == 2 || (nargin == 3 && strcmp(varargin{3}, 'void')))"
652  else:
653  methods_wrap += ' if nargin == 2'
654 
655  methods_wrap += " && isa(varargin{1}, 'uint64')"
656  methods_wrap += " && varargin{1} == uint64(5139824614673773682)\n"
657 
658  if is_virtual:
659  methods_wrap += textwrap.indent(textwrap.dedent('''\
660  if nargin == 2
661  my_ptr = varargin{{2}};
662  else
663  my_ptr = {wrapper_name}({id}, varargin{{2}});
664  end
665  ''').format(wrapper_name=self._wrapper_name(),
666  id=self._update_wrapper_id() + 1),
667  prefix=' ')
668  else:
669  methods_wrap += ' my_ptr = varargin{2};\n'
670 
671  collector_base_id = self._update_wrapper_id(
672  (namespace_name, inst_class, 'collectorInsertAndMakeBase', None),
673  id_diff=-1 if is_virtual else 0)
674 
675  methods_wrap += ' {ptr}{wrapper_name}({id}, my_ptr);\n' \
676  .format(
677  ptr='base_ptr = ' if has_parent else '',
678  wrapper_name=self._wrapper_name(),
679  id=collector_base_id - (1 if is_virtual else 0))
680 
681  for ctor in ctors:
682  wrapper_return = '[ my_ptr, base_ptr ] = ' \
683  if has_parent \
684  else 'my_ptr = '
685 
686  methods_wrap += textwrap.indent(textwrap.dedent('''\
687  elseif nargin == {len}{varargin}
688  {ptr}{wrapper}({num}{comma}{var_arg});
689  ''').format(len=len(ctor.args.list()),
690  varargin=self._wrap_variable_arguments(
691  ctor.args, False),
692  ptr=wrapper_return,
693  wrapper=self._wrapper_name(),
694  num=self._update_wrapper_id(
695  (namespace_name, inst_class, 'constructor', ctor)),
696  comma='' if len(ctor.args.list()) == 0 else ', ',
697  var_arg=self._wrap_list_variable_arguments(ctor.args)),
698  prefix=' ')
699 
700  base_obj = ''
701 
702  if has_parent:
703  base_obj = ' obj = obj@{parent_name}(uint64(5139824614673773682), base_ptr);'.format(
704  parent_name=parent_name)
705 
706  if base_obj:
707  base_obj = '\n' + base_obj
708 
709  methods_wrap += textwrap.indent(textwrap.dedent('''\
710  else
711  error('Arguments do not match any overload of {class_name_doc} constructor');
712  end{base_obj}
713  obj.ptr_{class_name} = my_ptr;
714  end\n
715  ''').format(namespace=namespace_name,
716  d='' if namespace_name == '' else '.',
717  class_name_doc=self._format_class_name(inst_class,
718  separator="."),
719  class_name=self._format_class_name(inst_class,
720  separator=""),
721  base_obj=base_obj),
722  prefix=' ')
723 
724  return methods_wrap
725 
726  def wrap_properties_block(self, class_name, inst_class):
727  """Generate Matlab properties block of the class.
728 
729  E.g.
730  ```
731  properties
732  ptr_gtsamISAM2Params = 0
733  relinearizeSkip
734  end
735  ```
736 
737  Args:
738  class_name: Class name with namespace to assign unique pointer.
739  inst_class: The instantiated class whose properties we want to wrap.
740 
741  Returns:
742  str: The `properties` block in a Matlab `classdef`.
743  """
744  # Get the property names and make into newline separated block
745  class_pointer = " ptr_{class_name} = 0".format(class_name=class_name)
746 
747  if len(inst_class.properties) > 0:
748  properties = '\n' + "\n".join(
749  [" {}".format(p.name) for p in inst_class.properties])
750  else:
751  properties = ''
752 
753  properties = class_pointer + properties
754  properties_block = textwrap.dedent('''\
755  properties
756  {properties}
757  end
758  ''').format(properties=properties)
759  return properties_block
760 
761  def wrap_class_properties(self, namespace_name: str,
762  inst_class: InstantiatedClass):
763  """Generate wrappers for the setters & getters of class properties.
764 
765  Args:
766  inst_class: The instantiated class whose properties we wish to wrap.
767  """
768  properties = []
769  for propty in inst_class.properties:
770  # These are the setters and getters in the .m file
771  function_name = namespace_name + inst_class.name + '_get_' + propty.name
772  getter = """
773  function varargout = get.{name}(this)
774  {varargout} = {wrapper}({num}, this);
775  this.{name} = {varargout};
776  end
777  """.format(name=propty.name,
778  varargout='varargout{1}',
779  wrapper=self._wrapper_name(),
780  num=self._update_wrapper_id(
781  (namespace_name, inst_class, propty.name, propty),
782  function_name=function_name))
783  properties.append(getter)
784 
785  # Setter doesn't need varargin since it needs just one input.
786  function_name = namespace_name + inst_class.name + '_set_' + propty.name
787  setter = """
788  function set.{name}(this, value)
789  obj.{name} = value;
790  {wrapper}({num}, this, value);
791  end
792  """.format(name=propty.name,
793  wrapper=self._wrapper_name(),
794  num=self._update_wrapper_id(
795  (namespace_name, inst_class, propty.name, propty),
796  function_name=function_name))
797  properties.append(setter)
798 
799  return properties
800 
801  def wrap_class_deconstructor(self, namespace_name, inst_class):
802  """Generate the delete function for the Matlab class."""
803  class_name = inst_class.name
804 
805  methods_text = textwrap.indent(textwrap.dedent("""\
806  function delete(obj)
807  {wrapper}({num}, obj.ptr_{class_name});
808  end\n
809  """).format(num=self._update_wrapper_id(
810  (namespace_name, inst_class, 'deconstructor', None)),
811  wrapper=self._wrapper_name(),
812  class_name="".join(inst_class.parent.full_namespaces()) +
813  class_name),
814  prefix=' ')
815 
816  return methods_text
817 
819  """Generate the display function for the Matlab class."""
820  return textwrap.indent(textwrap.dedent("""\
821  function display(obj), obj.print(''); end
822  %DISPLAY Calls print on the object
823  function disp(obj), obj.display; end
824  %DISP Calls print on the object
825  """),
826  prefix=' ')
827 
828  def _group_class_methods(self, methods):
829  """Group overloaded methods together"""
830  return self._group_methods(methods)
831 
832  @classmethod
833  def _format_varargout(cls, return_type, return_type_formatted):
834  """Determine format of return and varargout statements"""
835  if cls._return_count(return_type) == 1:
836  varargout = '' \
837  if return_type_formatted == 'void' \
838  else 'varargout{1} = '
839  else:
840  varargout = '[ varargout{1} varargout{2} ] = '
841 
842  return varargout
843 
845  namespace_name,
846  inst_class,
847  methods,
848  serialize=(False, )):
849  """Wrap the methods in the class.
850 
851  Args:
852  namespace_name: the name of the class's namespace
853  inst_class: the instantiated class whose methods to wrap
854  methods: the methods to wrap in the order to wrap them
855  serialize: mutable param storing if one of the methods is serialize
856  """
857  method_text = ''
858 
859  methods = self._group_class_methods(methods)
860 
861  # Convert to list so that it is mutable
862  if isinstance(serialize, tuple):
863  serialize = list(serialize)
864 
865  for method in methods:
866  method_name = method[0].name
867  if method_name in self.whitelist and method_name != 'serialize':
868  continue
869  if method_name in self.ignore_methods:
870  continue
871 
872  if method_name == 'serialize':
873  if self.use_boost_serialization:
874  serialize[0] = True
875  method_text += self.wrap_class_serialize_method(
876  namespace_name, inst_class)
877 
878  else:
879  # Generate method code
880  method_text += textwrap.indent(textwrap.dedent("""\
881  function varargout = {method_name}(this, varargin)
882  """).format(caps_name=method_name.upper(),
883  method_name=method_name),
884  prefix='')
885 
886  for overload in method:
887  method_text += textwrap.indent(textwrap.dedent("""\
888  % {caps_name} usage: {method_name}(""").format(
889  caps_name=method_name.upper(),
890  method_name=method_name),
891  prefix=' ')
892 
893  # Determine format of return and varargout statements
894  return_type_formatted = self._format_return_type(
895  overload.return_type,
896  include_namespace=True,
897  separator=".")
898  varargout = self._format_varargout(overload.return_type,
899  return_type_formatted)
900 
901  check_statement = self._wrap_method_check_statement(
902  overload.args)
903  class_name = namespace_name + ('' if namespace_name == ''
904  else '.') + inst_class.name
905 
906  end_statement = '' \
907  if check_statement == '' \
908  else textwrap.indent(textwrap.dedent("""\
909  return
910  end
911  """).format(
912  class_name=class_name,
913  method_name=overload.original.name), prefix=' ')
914 
915  method_text += textwrap.dedent("""\
916  {method_args}) : returns {return_type}
917  % Doxygen can be found at https://gtsam.org/doxygen/
918  {check_statement}{spacing}{varargout}{wrapper}({num}, this, varargin{{:}});
919  {end_statement}""").format(
920  method_args=self._wrap_args(overload.args),
921  return_type=return_type_formatted,
922  num=self._update_wrapper_id(
923  (namespace_name, inst_class,
924  overload.original.name, overload)),
925  check_statement=check_statement,
926  spacing='' if check_statement == '' else ' ',
927  varargout=varargout,
928  wrapper=self._wrapper_name(),
929  end_statement=end_statement)
930 
931  final_statement = textwrap.indent(textwrap.dedent("""\
932  error('Arguments do not match any overload of function {class_name}.{method_name}');
933  """.format(class_name=class_name, method_name=method_name)),
934  prefix=' ')
935  method_text += final_statement + 'end\n\n'
936 
937  return method_text
938 
939  def wrap_static_methods(self, namespace_name, instantiated_class,
940  serialize):
941  """
942  Wrap the static methods in the class.
943  """
944  class_name = instantiated_class.name
945 
946  method_text = 'methods(Static = true)\n'
947  static_methods = sorted(instantiated_class.static_methods,
948  key=lambda name: name.name)
949 
950  static_methods = self._group_class_methods(static_methods)
951 
952  for static_method in static_methods:
953  format_name = list(static_method[0].name)
954  format_name[0] = format_name[0]
955 
956  if static_method[0].name in self.ignore_methods:
957  continue
958 
959  method_text += textwrap.indent(textwrap.dedent('''\
960  function varargout = {name}(varargin)
961  '''.format(name=''.join(format_name))),
962  prefix=" ")
963 
964  for static_overload in static_method:
965  check_statement = self._wrap_method_check_statement(
966  static_overload.args)
967 
968  end_statement = '' \
969  if check_statement == '' \
970  else textwrap.indent(textwrap.dedent("""
971  return
972  end
973  """), prefix='')
974  method_text += textwrap.indent(textwrap.dedent('''\
975  % {name_caps} usage: {name_upper_case}({args}) : returns {return_type}
976  % Doxygen can be found at https://gtsam.org/doxygen/
977  {check_statement}{spacing}varargout{{1}} = {wrapper}({id}, varargin{{:}});{end_statement}
978  ''').format(
979  name=''.join(format_name),
980  name_caps=static_overload.name.upper(),
981  name_upper_case=static_overload.name,
982  args=self._wrap_args(static_overload.args),
983  return_type=self._format_return_type(
984  static_overload.return_type,
985  include_namespace=True,
986  separator="."),
987  length=len(static_overload.args.list()),
988  var_args_list=self._wrap_variable_arguments(
989  static_overload.args),
990  check_statement=check_statement,
991  spacing='' if check_statement == '' else ' ',
992  wrapper=self._wrapper_name(),
993  id=self._update_wrapper_id(
994  (namespace_name, instantiated_class,
995  static_overload.name, static_overload)),
996  class_name=instantiated_class.name,
997  end_statement=end_statement),
998  prefix=' ')
999 
1000  # If the arguments don't match any of the checks above,
1001  # throw an error with the class and method name.
1002  method_text += textwrap.indent(textwrap.dedent("""\
1003  error('Arguments do not match any overload of function {class_name}.{method_name}');
1004  """.format(class_name=class_name,
1005  method_name=static_overload.name)),
1006  prefix=' ')
1007 
1008  method_text += textwrap.indent(textwrap.dedent("""\
1009  end\n
1010  """),
1011  prefix=" ")
1012 
1013  if serialize and self.use_boost_serialization:
1014  method_text += WrapperTemplate.matlab_deserialize.format(
1015  class_name=namespace_name + '.' + instantiated_class.name,
1016  wrapper=self._wrapper_name(),
1017  id=self._update_wrapper_id(
1018  (namespace_name, instantiated_class, 'string_deserialize',
1019  'deserialize')))
1020 
1021  return method_text
1022 
1024  instantiated_class,
1025  namespace_name: str = ''):
1026  """Generate comments and code for given class.
1027 
1028  Args:
1029  instantiated_class: template_instantiator.InstantiatedClass
1030  instance storing the class to wrap
1031  namespace_name: the name of the namespace if there is one
1032  """
1033  file_name = self._clean_class_name(instantiated_class)
1034  namespace_file_name = namespace_name + file_name
1035 
1036  uninstantiated_name = "::".join(instantiated_class.namespaces()
1037  [1:]) + "::" + instantiated_class.name
1038  if uninstantiated_name in self.ignore_classes:
1039  return None
1040 
1041  # Class docstring/comment
1042  content_text = self.class_comment(instantiated_class)
1043  content_text += self.wrap_methods(instantiated_class.methods)
1044 
1045  # Class definition
1046  # if namespace_name:
1047  # print("nsname: {}, file_name_: {}, filename: {}"
1048  # .format(namespace_name,
1049  # self._clean_class_name(instantiated_class), file_name)
1050  # , file=sys.stderr)
1051  content_text += 'classdef {class_name} < {parent}\n'.format(
1052  class_name=file_name,
1053  parent=str(self._qualified_name(
1054  instantiated_class.parent_class)).replace("::", "."))
1055 
1056  # Class properties
1057  content_text += ' ' + reduce(
1058  self._insert_spaces,
1059  self.wrap_properties_block(namespace_file_name,
1060  instantiated_class).splitlines()) + '\n'
1061 
1062  # Class constructor
1063  content_text += ' ' + reduce(
1064  self._insert_spaces,
1066  namespace_name,
1067  instantiated_class,
1068  instantiated_class.parent_class,
1069  instantiated_class.ctors,
1070  instantiated_class.is_virtual,
1071  ).splitlines()) + '\n'
1072 
1073  # Delete function
1074  content_text += ' ' + reduce(
1075  self._insert_spaces,
1077  namespace_name, instantiated_class).splitlines()) + '\n'
1078 
1079  # Display function
1080  content_text += ' ' + reduce(
1081  self._insert_spaces,
1082  self.wrap_class_display().splitlines()) + '\n'
1083 
1084  # Class methods
1085  serialize = [False]
1086 
1087  if len(instantiated_class.methods) != 0:
1088  methods = sorted(instantiated_class.methods,
1089  key=lambda name: name.name)
1090  class_methods_wrapped = self.wrap_class_methods(
1091  namespace_name,
1092  instantiated_class,
1093  methods,
1094  serialize=serialize).splitlines()
1095  if len(class_methods_wrapped) > 0:
1096  content_text += ' ' + reduce(
1097  lambda x, y: x + '\n' + ('' if y == '' else ' ') + y,
1098  class_methods_wrapped) + '\n'
1099 
1100  # Class properties
1101  if len(instantiated_class.properties) != 0:
1102  property_accessors = self.wrap_class_properties(
1103  namespace_name, instantiated_class)
1104  content_text += textwrap.indent(textwrap.dedent(
1105  "".join(property_accessors)),
1106  prefix=' ')
1107 
1108  content_text += ' end' # End the `methods` block
1109 
1110  # Static class methods
1111  content_text += '\n\n ' + reduce(
1112  self._insert_spaces,
1113  self.wrap_static_methods(namespace_name, instantiated_class,
1114  serialize[0]).splitlines()) + '\n' + \
1115  ' end\n'
1116 
1117  # Close the classdef
1118  content_text += textwrap.dedent('''\
1119  end
1120  ''')
1121 
1122  # Enums
1123  # Place enums into the correct submodule so we can access them
1124  # e.g. gtsam.Class.Enum.A
1125  for enum in instantiated_class.enums:
1126  enum_text = self.wrap_enum(enum)
1127  if namespace_name != '':
1128  submodule = f"+{namespace_name}/"
1129  else:
1130  submodule = ""
1131  submodule += f"+{instantiated_class.name}"
1132  self.content.append((submodule, [enum_text]))
1133 
1134  return file_name + '.m', content_text
1135 
1136  def wrap_enum(self, enum):
1137  """
1138  Wrap an enum definition as a Matlab class.
1139 
1140  Args:
1141  enum: The interface_parser.Enum instance
1142  """
1143  file_name = enum.name + '.m'
1144  enum_template = textwrap.dedent("""\
1145  classdef {0} < uint32
1146  enumeration
1147  {1}
1148  end
1149  end
1150  """)
1151  enumerators = "\n ".join([
1152  f"{enumerator.name}({idx})"
1153  for idx, enumerator in enumerate(enum.enumerators)
1154  ])
1155 
1156  content = enum_template.format(enum.name, enumerators)
1157  return file_name, content
1158 
1159  def wrap_namespace(self, namespace, add_mex_file=True):
1160  """Wrap a namespace by wrapping all of its components.
1161 
1162  Args:
1163  namespace: the interface_parser.namespace instance of the namespace
1164  add_cpp_file: Flag indicating whether the mex file should be added
1165  """
1166  namespaces = namespace.full_namespaces()
1167  inner_namespace = namespace.name != ''
1168  wrapped = []
1169 
1170  top_level_scope = []
1171  inner_namespace_scope = []
1172 
1173  for element in namespace.content:
1174  if isinstance(element, parser.Include):
1175  self.includes.append(element)
1176 
1177  elif isinstance(element, parser.Namespace):
1178  self.wrap_namespace(element, False)
1179 
1180  elif isinstance(element, parser.Enum):
1181  file, content = self.wrap_enum(element)
1182  if inner_namespace:
1183  module = "".join([
1184  '+' + x + '/' for x in namespace.full_namespaces()[1:]
1185  ])[:-1]
1186  inner_namespace_scope.append((module, [(file, content)]))
1187  else:
1188  top_level_scope.append((file, content))
1189 
1190  elif isinstance(element, instantiator.InstantiatedClass):
1191  self.add_class(element)
1192 
1193  if inner_namespace:
1194  class_text = self.wrap_instantiated_class(
1195  element, "".join(namespace.full_namespaces()))
1196 
1197  if not class_text is None:
1198  inner_namespace_scope.append(("".join([
1199  '+' + x + '/'
1200  for x in namespace.full_namespaces()[1:]
1201  ])[:-1], [(class_text[0], class_text[1])]))
1202  else:
1203  class_text = self.wrap_instantiated_class(element)
1204  top_level_scope.append((class_text[0], class_text[1]))
1205 
1206  self.content.extend(top_level_scope)
1207 
1208  if inner_namespace:
1209  self.content.append(inner_namespace_scope)
1210 
1211  if add_mex_file:
1212  cpp_filename = self._wrapper_name() + '.cpp'
1213  self.content.append((cpp_filename, self.wrapper_file_headers))
1214 
1215  # Global functions
1216  all_funcs = [
1217  func for func in namespace.content
1218  if isinstance(func, parser.GlobalFunction)
1219  ]
1220 
1221  self.wrap_methods(all_funcs, True, global_ns=namespace)
1222 
1223  return wrapped
1224 
1226  return_type_name,
1227  shared_obj,
1228  func_id,
1229  new_line=True):
1230  """Wrap the collector function which returns a shared pointer."""
1231  new_line = '\n' if new_line else ''
1232 
1233  return WrapperTemplate.collector_function_shared_return.format(
1234  name=self._format_type_name(return_type_name,
1235  include_namespace=False),
1236  shared_obj=shared_obj,
1237  id=func_id,
1238  new_line=new_line)
1239 
1240  def wrap_collector_function_return_types(self, return_type, func_id):
1241  """
1242  Wrap the return type of the collector function when a std::pair is returned.
1243  """
1244  return_type_text = ' out[' + str(func_id) + '] = '
1245  pair_value = 'first' if func_id == 0 else 'second'
1246  new_line = '\n' if func_id == 0 else ''
1247 
1248  if self.is_shared_ptr(return_type) or self.is_ptr(return_type) or \
1249  self.can_be_pointer(return_type):
1250  shared_obj = 'pairResult.' + pair_value
1251 
1252  if not (return_type.is_shared_ptr or return_type.is_ptr):
1253  shared_obj = 'std::make_shared<{name}>({shared_obj})' \
1254  .format(name=self._format_type_name(return_type.typename),
1255  shared_obj='pairResult.' + pair_value)
1256 
1257  if return_type.typename.name in self.ignore_namespace:
1258  return_type_text = self.wrap_collector_function_shared_return(
1259  return_type.typename, shared_obj, func_id, func_id == 0)
1260  else:
1261  return_type_text += 'wrap_shared_ptr({0},"{1}", false);{new_line}' \
1262  .format(shared_obj,
1263  self._format_type_name(return_type.typename,
1264  separator='.'),
1265  new_line=new_line)
1266  else:
1267  return_type_text += 'wrap< {0} >(pairResult.{1});{2}'.format(
1268  self._format_type_name(return_type.typename, separator='.'),
1269  pair_value, new_line)
1270 
1271  return return_type_text
1272 
1274  obj: str,
1275  ctype: parser.Type,
1276  instantiated_class: InstantiatedClass = None):
1277  """Helper method to get the final statement before the return in the collector function."""
1278  expanded = ''
1279 
1280  if instantiated_class and \
1281  self.is_enum(ctype, instantiated_class):
1282  if self.is_class_enum(ctype, instantiated_class):
1283  class_name = ".".join(instantiated_class.namespaces()[1:] +
1284  [instantiated_class.name])
1285  else:
1286  # Get the full namespace
1287  class_name = ".".join(
1288  instantiated_class.parent.full_namespaces()[1:])
1289 
1290  if class_name != "":
1291  class_name += '.'
1292 
1293  enum_type = f"{class_name}{ctype.typename.name}"
1294  expanded = textwrap.indent(
1295  f'out[0] = wrap_enum({obj},\"{enum_type}\");', prefix=' ')
1296 
1297  elif self.is_shared_ptr(ctype) or self.is_ptr(ctype) or \
1298  self.can_be_pointer(ctype):
1299  sep_method_name = partial(self._format_type_name,
1300  ctype.typename,
1301  include_namespace=True)
1302 
1303  if ctype.typename.name in self.ignore_namespace:
1304  expanded += self.wrap_collector_function_shared_return(
1305  ctype.typename, obj, 0, new_line=False)
1306 
1307  if ctype.is_shared_ptr or ctype.is_ptr:
1308  shared_obj = '{obj},"{method_name_sep}"'.format(
1309  obj=obj, method_name_sep=sep_method_name('.'))
1310  else:
1311  method_name_sep_dot = sep_method_name('.')
1312 
1313  # Specialize for std::optional so we access the underlying member
1314  #TODO(Varun) How do we handle std::optional as a Mex type?
1315  if isinstance(ctype, parser.TemplatedType) and \
1316  "std::optional" == str(ctype.typename)[:13]:
1317  obj = f"*{obj}"
1318  type_name = ctype.template_params[0].typename
1319  method_name_sep_dot = ".".join(
1320  type_name.namespaces) + f".{type_name.name}"
1321 
1322 
1323  shared_obj_template = 'std::make_shared<{method_name_sep_col}>({obj}),' \
1324  '"{method_name_sep_dot}"'
1325  shared_obj = shared_obj_template \
1326  .format(method_name_sep_col=sep_method_name(),
1327  method_name_sep_dot=method_name_sep_dot,
1328  obj=obj)
1329 
1330  if ctype.typename.name not in self.ignore_namespace:
1331  expanded += textwrap.indent(
1332  'out[0] = wrap_shared_ptr({0}, false);'.format(shared_obj),
1333  prefix=' ')
1334  else:
1335  expanded += ' out[0] = wrap< {0} >({1});'.format(
1336  ctype.typename.name, obj)
1337 
1338  return expanded
1339 
1340  def wrap_collector_function_return(self, method, instantiated_class=None):
1341  """
1342  Wrap the complete return type of the function.
1343  """
1344  expanded = ''
1345 
1346  params = self._wrapper_unwrap_arguments(
1347  method.args, arg_id=1, instantiated_class=instantiated_class)[0]
1348 
1349  return_1 = method.return_type.type1
1350  return_count = self._return_count(method.return_type)
1351  return_1_name = method.return_type.type1.typename.name
1352  obj_start = ''
1353 
1354  if isinstance(method, instantiator.InstantiatedMethod):
1355  method_name = method.to_cpp()
1356  obj_start = 'obj->'
1357 
1358  if method.instantiations:
1359  # method_name += '<{}>'.format(
1360  # self._format_type_name(method.instantiations))
1361  method = method.to_cpp()
1362 
1363  elif isinstance(method, instantiator.InstantiatedStaticMethod):
1364  method_name = self._format_static_method(method, '::')
1365  method_name += method.original.name
1366 
1367  elif isinstance(method, parser.GlobalFunction):
1368  method_name = self._format_global_function(method, '::')
1369  method_name += method.name
1370 
1371  else:
1372  if isinstance(method.parent, instantiator.InstantiatedClass):
1373  method_name = method.parent.to_cpp() + "::"
1374  else:
1375  method_name = self._format_static_method(method, '::')
1376  method_name += method.name
1377 
1378  obj = ' ' if return_1_name == 'void' else ''
1379  obj += '{}{}({})'.format(obj_start, method_name, params)
1380 
1381  if return_1_name != 'void':
1382  if return_count == 1:
1383  expanded += self._collector_return(
1384  obj, return_1, instantiated_class=instantiated_class)
1385 
1386  elif return_count == 2:
1387  return_2 = method.return_type.type2
1388 
1389  expanded += ' auto pairResult = {};\n'.format(obj)
1390  expanded += self.wrap_collector_function_return_types(
1391  return_1, 0)
1392  expanded += self.wrap_collector_function_return_types(
1393  return_2, 1)
1394  else:
1395  expanded += obj + ';'
1396 
1397  return expanded
1398 
1400  self,
1401  class_property: parser.Variable,
1402  instantiated_class: InstantiatedClass = None):
1403  """Get the last collector function statement before return for a property."""
1404  property_name = class_property.name
1405  obj = 'obj->{}'.format(property_name)
1406 
1407  return self._collector_return(obj,
1408  class_property.ctype,
1409  instantiated_class=instantiated_class)
1410 
1411  def wrap_collector_function_upcast_from_void(self, class_name, func_id,
1412  cpp_name):
1413  """
1414  Add function to upcast type from void type.
1415  """
1416  return WrapperTemplate.collector_function_upcast_from_void.format(
1417  class_name=class_name, cpp_name=cpp_name, id=func_id)
1418 
1419  def generate_collector_function(self, func_id):
1420  """
1421  Generate the complete collector function that goes into the wrapper.cpp file.
1422 
1423  A collector function is the Mex function used to interact between
1424  the C++ object and the Matlab .m files.
1425  """
1426  collector_func = self.wrapper_map.get(func_id)
1427 
1428  if collector_func is None:
1429  return ''
1430 
1431  method_name = collector_func[3]
1432 
1433  collector_function = "void {}" \
1434  "(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n".format(method_name)
1435 
1436  if isinstance(collector_func[1], instantiator.InstantiatedClass):
1437  body = '{\n'
1438 
1439  extra = collector_func[4]
1440 
1441  class_name = collector_func[0] + collector_func[1].name
1442  class_name_separated = collector_func[1].to_cpp()
1443  is_method = isinstance(extra, parser.Method)
1444  is_static_method = isinstance(extra, parser.StaticMethod)
1445  is_property = isinstance(extra, parser.Variable)
1446 
1447  if collector_func[2] == 'collectorInsertAndMakeBase':
1448  body += textwrap.indent(textwrap.dedent('''\
1449  mexAtExit(&_deleteAllObjects);
1450  typedef std::shared_ptr<{class_name_sep}> Shared;\n
1451  Shared *self = *reinterpret_cast<Shared**> (mxGetData(in[0]));
1452  collector_{class_name}.insert(self);
1453  ''').format(class_name_sep=class_name_separated,
1454  class_name=class_name),
1455  prefix=' ')
1456 
1457  if collector_func[1].parent_class:
1458  body += textwrap.indent(textwrap.dedent('''
1459  typedef std::shared_ptr<{}> SharedBase;
1460  out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
1461  *reinterpret_cast<SharedBase**>(mxGetData(out[0])) = new SharedBase(*self);
1462  ''').format(collector_func[1].parent_class),
1463  prefix=' ')
1464 
1465  elif collector_func[2] == 'constructor':
1466  base = ''
1467  params, body_args = self._wrapper_unwrap_arguments(
1468  extra.args, instantiated_class=collector_func[1])
1469 
1470  if collector_func[1].parent_class:
1471  base += textwrap.indent(textwrap.dedent('''
1472  typedef std::shared_ptr<{}> SharedBase;
1473  out[1] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
1474  *reinterpret_cast<SharedBase**>(mxGetData(out[1])) = new SharedBase(*self);
1475  ''').format(collector_func[1].parent_class),
1476  prefix=' ')
1477 
1478  body += textwrap.dedent('''\
1479  mexAtExit(&_deleteAllObjects);
1480  typedef std::shared_ptr<{class_name_sep}> Shared;\n
1481  {body_args} Shared *self = new Shared(new {class_name_sep}({params}));
1482  collector_{class_name}.insert(self);
1483  out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);
1484  *reinterpret_cast<Shared**> (mxGetData(out[0])) = self;
1485  {base}''').format(class_name_sep=class_name_separated,
1486  body_args=body_args,
1487  params=params,
1488  class_name=class_name,
1489  base=base)
1490 
1491  elif collector_func[2] == 'deconstructor':
1492  body += textwrap.indent(textwrap.dedent('''\
1493  typedef std::shared_ptr<{class_name_sep}> Shared;
1494  checkArguments("delete_{class_name}",nargout,nargin,1);
1495  Shared *self = *reinterpret_cast<Shared**>(mxGetData(in[0]));
1496  Collector_{class_name}::iterator item;
1497  item = collector_{class_name}.find(self);
1498  if(item != collector_{class_name}.end()) {{
1499  collector_{class_name}.erase(item);
1500  }}
1501  delete self;
1502  ''').format(class_name_sep=class_name_separated,
1503  class_name=class_name),
1504  prefix=' ')
1505 
1506  elif extra == 'serialize':
1507  if self.use_boost_serialization:
1508  body += self.wrap_collector_function_serialize(
1509  collector_func[1].name,
1510  full_name=collector_func[1].to_cpp(),
1511  namespace=collector_func[0])
1512 
1513  elif extra == 'deserialize':
1514  if self.use_boost_serialization:
1516  collector_func[1].name,
1517  full_name=collector_func[1].to_cpp(),
1518  namespace=collector_func[0])
1519 
1520  elif is_method or is_static_method:
1521  method_name = ''
1522 
1523  if is_static_method:
1524  method_name = self._format_static_method(extra, '.')
1525 
1526  method_name += extra.name
1527 
1528  _, body_args = self._wrapper_unwrap_arguments(
1529  extra.args,
1530  arg_id=1 if is_method else 0,
1531  instantiated_class=collector_func[1])
1532 
1533  return_body = self.wrap_collector_function_return(
1534  extra, collector_func[1])
1535 
1536  shared_obj = ''
1537 
1538  if is_method:
1539  shared_obj = ' auto obj = unwrap_shared_ptr<{class_name_sep}>' \
1540  '(in[0], "ptr_{class_name}");\n'.format(
1541  class_name_sep=class_name_separated,
1542  class_name=class_name)
1543 
1544  body += ' checkArguments("{method_name}",nargout,nargin{min1},' \
1545  '{num_args});\n' \
1546  '{shared_obj}' \
1547  '{body_args}' \
1548  '{return_body}\n'.format(
1549  min1='-1' if is_method else '',
1550  shared_obj=shared_obj,
1551  method_name=method_name,
1552  num_args=len(extra.args.list()),
1553  body_args=body_args,
1554  return_body=return_body)
1555 
1556  elif is_property:
1557  shared_obj = ' auto obj = unwrap_shared_ptr<{class_name_sep}>' \
1558  '(in[0], "ptr_{class_name}");\n'.format(
1559  class_name_sep=class_name_separated,
1560  class_name=class_name)
1561 
1562  # Unpack the property from mxArray
1563  property_type, unwrap = self._unwrap_argument(
1564  extra, arg_id=1, instantiated_class=collector_func[1])
1565  unpack_property = textwrap.indent(textwrap.dedent('''\
1566  {arg_type} {name} = {unwrap}
1567  '''.format(arg_type=property_type,
1568  name=extra.name,
1569  unwrap=unwrap)),
1570  prefix=' ')
1571 
1572  # Getter
1573  if "_get_" in method_name:
1574  return_body = self.wrap_collector_property_return(
1575  extra, instantiated_class=collector_func[1])
1576 
1577  getter = ' checkArguments("{property_name}",nargout,nargin{min1},' \
1578  '{num_args});\n' \
1579  '{shared_obj}' \
1580  '{return_body}\n'.format(
1581  property_name=extra.name,
1582  min1='-1',
1583  num_args=0,
1584  shared_obj=shared_obj,
1585  return_body=return_body)
1586 
1587  body += getter
1588 
1589  # Setter
1590  if "_set_" in method_name:
1591  is_ptr_type = self.can_be_pointer(extra.ctype) and \
1592  not self.is_enum(extra.ctype, collector_func[1])
1593  return_body = ' obj->{0} = {1}{0};'.format(
1594  extra.name, '*' if is_ptr_type else '')
1595 
1596  setter = ' checkArguments("{property_name}",nargout,nargin{min1},' \
1597  '{num_args});\n' \
1598  '{shared_obj}' \
1599  '{unpack_property}' \
1600  '{return_body}\n'.format(
1601  property_name=extra.name,
1602  min1='-1',
1603  num_args=1,
1604  shared_obj=shared_obj,
1605  unpack_property=unpack_property,
1606  return_body=return_body)
1607 
1608  body += setter
1609 
1610  body += '}\n'
1611 
1612  if extra not in ['serialize', 'deserialize']:
1613  body += '\n'
1614 
1615  collector_function += body
1616 
1617  else:
1618  body = textwrap.dedent('''\
1619  {{
1620  checkArguments("{function_name}",nargout,nargin,{len});
1621  ''').format(function_name=collector_func[1].name,
1622  id=self.global_function_id,
1623  len=len(collector_func[1].args.list()))
1624 
1625  body += self._wrapper_unwrap_arguments(collector_func[1].args)[1]
1626  body += self.wrap_collector_function_return(
1627  collector_func[1]) + '\n}\n'
1628 
1629  collector_function += body
1630 
1631  self.global_function_id += 1
1632 
1633  return collector_function
1634 
1635  def mex_function(self):
1636  """
1637  Generate the wrapped MEX function.
1638  """
1639  cases = ''
1640  next_case = None
1641 
1642  for wrapper_id in range(self.wrapper_id):
1643  id_val = self.wrapper_map.get(wrapper_id)
1644  set_next_case = False
1645 
1646  if id_val is None:
1647  id_val = self.wrapper_map.get(wrapper_id + 1)
1648 
1649  if id_val is None:
1650  continue
1651 
1652  set_next_case = True
1653 
1654  cases += textwrap.indent(textwrap.dedent('''\
1655  case {}:
1656  {}(nargout, out, nargin-1, in+1);
1657  break;
1658  ''').format(wrapper_id, next_case if next_case else id_val[3]),
1659  prefix=' ')
1660 
1661  if set_next_case:
1662  next_case = '{}_upcastFromVoid_{}'.format(
1663  id_val[1].name, wrapper_id + 1)
1664  else:
1665  next_case = None
1666 
1667  mex_function = WrapperTemplate.mex_function.format(
1668  module_name=self.module_name, cases=cases)
1669 
1670  return mex_function
1671 
1672  def get_class_name(self, cls):
1673  """Get the name of the class `cls` taking template instantiations into account."""
1674  if cls.instantiations:
1675  class_name_sep = cls.name
1676  else:
1677  class_name_sep = cls.to_cpp()
1678 
1679  class_name = self._format_class_name(cls)
1680 
1681  return class_name, class_name_sep
1682 
1684  """
1685  Generate the preamble of the wrapper file, which includes
1686  the Boost exports, typedefs for collectors, and
1687  the _deleteAllObjects and _RTTIRegister functions.
1688  """
1689  delete_objs = ''
1690  typedef_instances = []
1691  boost_class_export_guid = ''
1692  typedef_collectors = ''
1693  rtti_classes = ''
1694 
1695  for cls in self.classes:
1696  # Check if class is in ignore list.
1697  # If so, then skip
1698  uninstantiated_name = "::".join(cls.namespaces()[1:] + [cls.name])
1699  if uninstantiated_name in self.ignore_classes:
1700  continue
1701 
1702  class_name, class_name_sep = self.get_class_name(cls)
1703 
1704  # If a class has instantiations, then declare the typedef for each instance
1705  if cls.instantiations:
1706  cls_insts = ''
1707  for i, inst in enumerate(cls.instantiations):
1708  if i != 0:
1709  cls_insts += ', '
1710 
1711  cls_insts += self._format_type_name(inst)
1712 
1713  typedef_instances.append('typedef {original_class_name} {class_name_sep};' \
1714  .format(original_class_name=cls.to_cpp(),
1715  class_name_sep=cls.name))
1716 
1717  # Get the Boost exports for serialization
1718  if self.use_boost_serialization and \
1719  cls.original.namespaces() and self._has_serialization(cls):
1720  boost_class_export_guid += 'BOOST_CLASS_EXPORT_GUID({}, "{}");\n'.format(
1721  class_name_sep, class_name)
1722 
1723  # Typedef and declare the collector objects.
1724  typedef_collectors += WrapperTemplate.typdef_collectors.format(
1725  class_name_sep=class_name_sep, class_name=class_name)
1726 
1727  # Generate the _deleteAllObjects method
1728  delete_objs += WrapperTemplate.delete_obj.format(
1729  class_name=class_name)
1730 
1731  if cls.is_virtual:
1732  class_name, class_name_sep = self.get_class_name(cls)
1733  rtti_classes += ' types.insert(std::make_pair(typeid({}).name(), "{}"));\n' \
1734  .format(class_name_sep, class_name)
1735 
1736  # Generate the typedef instances string
1737  typedef_instances = "\n".join(typedef_instances)
1738 
1739  # Generate the full deleteAllObjects function
1740  delete_all_objs = WrapperTemplate.delete_all_objects.format(
1741  delete_objs=delete_objs)
1742 
1743  # Generate the full RTTIRegister function
1744  rtti_register = WrapperTemplate.rtti_register.format(
1745  module_name=self.module_name, rtti_classes=rtti_classes)
1746 
1747  return typedef_instances, boost_class_export_guid, \
1748  typedef_collectors, delete_all_objs, rtti_register
1749 
1750  def generate_wrapper(self, namespace):
1751  """Generate the c++ wrapper."""
1752  assert namespace, "Namespace if empty"
1753 
1754  # Generate the header includes
1755  includes_list = sorted(self.includes,
1756  key=lambda include: include.header)
1757 
1758  # If boost serialization is enabled, include serialization headers
1759  if self.use_boost_serialization:
1760  boost_headers = WrapperTemplate.boost_headers
1761  else:
1762  boost_headers = ""
1763 
1764  includes = textwrap.dedent("""\
1765  {wrapper_file_headers}
1766  {boost_headers}
1767  {includes_list}
1768  """).format(wrapper_file_headers=self.wrapper_file_headers.strip(),
1769  boost_headers=boost_headers,
1770  includes_list='\n'.join(map(str, includes_list)))
1771 
1772  preamble = self.generate_preamble()
1773  typedef_instances, boost_class_export_guid, \
1774  typedef_collectors, delete_all_objs, \
1775  rtti_register = preamble
1776 
1777  ptr_ctor_frag = ''
1778  set_next_case = False
1779 
1780  for idx in range(self.wrapper_id):
1781  id_val = self.wrapper_map.get(idx)
1782  queue_set_next_case = set_next_case
1783 
1784  set_next_case = False
1785 
1786  if id_val is None:
1787  id_val = self.wrapper_map.get(idx + 1)
1788 
1789  if id_val is None:
1790  continue
1791 
1792  set_next_case = True
1793 
1794  ptr_ctor_frag += self.generate_collector_function(idx)
1795 
1796  if queue_set_next_case:
1797  ptr_ctor_frag += self.wrap_collector_function_upcast_from_void(
1798  id_val[1].name, idx, id_val[1].to_cpp())
1799 
1800  wrapper_file = textwrap.dedent('''\
1801  {includes}
1802  {typedef_instances}
1803  {boost_class_export_guid}
1804  {typedefs_collectors}
1805  {delete_all_objs}
1806  {rtti_register}
1807  {pointer_constructor_fragment}{mex_function}''') \
1808  .format(includes=includes,
1809  typedef_instances=typedef_instances,
1810  boost_class_export_guid=boost_class_export_guid,
1811  typedefs_collectors=typedef_collectors,
1812  delete_all_objs=delete_all_objs,
1813  rtti_register=rtti_register,
1814  pointer_constructor_fragment=ptr_ctor_frag,
1815  mex_function=self.mex_function())
1816 
1817  self.content.append((self._wrapper_name() + '.cpp', wrapper_file))
1818 
1819  def wrap_class_serialize_method(self, namespace_name, inst_class):
1820  """
1821  Wrap the serizalize method of the class.
1822  """
1823  class_name = inst_class.name
1824  wrapper_id = self._update_wrapper_id(
1825  (namespace_name, inst_class, 'string_serialize', 'serialize'))
1826 
1827  return WrapperTemplate.class_serialize_method.format(
1828  wrapper=self._wrapper_name(),
1829  wrapper_id=wrapper_id,
1830  class_name=namespace_name + '.' + class_name)
1831 
1833  class_name,
1834  full_name='',
1835  namespace=''):
1836  """
1837  Wrap the serizalize collector function.
1838  """
1839  return WrapperTemplate.collector_function_serialize.format(
1840  class_name=class_name, full_name=full_name, namespace=namespace)
1841 
1843  class_name,
1844  full_name='',
1845  namespace=''):
1846  """
1847  Wrap the deserizalize collector function.
1848  """
1849  return WrapperTemplate.collector_function_deserialize.format(
1850  class_name=class_name, full_name=full_name, namespace=namespace)
1851 
1852  def generate_content(self, cc_content, path):
1853  """
1854  Generate files and folders from matlab wrapper content.
1855 
1856  Args:
1857  cc_content: The content to generate formatted as
1858  (file_name, file_content) or
1859  (folder_name, [(file_name, file_content)])
1860  path: The path to the files parent folder within the main folder
1861  """
1862  for c in cc_content:
1863  if isinstance(c, list):
1864  # c is a namespace
1865  if len(c) == 0:
1866  continue
1867 
1868  path_to_folder = osp.join(path, c[0][0])
1869 
1870  if not osp.isdir(path_to_folder):
1871  try:
1872  os.makedirs(path_to_folder, exist_ok=True)
1873  except OSError:
1874  pass
1875 
1876  for sub_content in c:
1877  self.generate_content(sub_content[1], path_to_folder)
1878 
1879  elif isinstance(c[1], list):
1880  # c is a wrapped function
1881  path_to_folder = osp.join(path, c[0])
1882 
1883  if not osp.isdir(path_to_folder):
1884  try:
1885  os.makedirs(path_to_folder, exist_ok=True)
1886  except OSError:
1887  pass
1888 
1889  for sub_content in c[1]:
1890  path_to_file = osp.join(path_to_folder, sub_content[0])
1891  with open(path_to_file, 'w') as f:
1892  f.write(sub_content[1])
1893  else:
1894  # c is a wrapped class
1895  path_to_file = osp.join(path, c[0])
1896 
1897  if not osp.isdir(path_to_file):
1898  try:
1899  os.mkdir(path)
1900  except OSError:
1901  pass
1902 
1903  with open(path_to_file, 'w') as f:
1904  f.write(c[1])
1905 
1906  def wrap(self, files, path):
1907  """High level function to wrap the project."""
1908  content = ""
1909  modules = {}
1910  for file in files:
1911  with open(file, 'r') as f:
1912  content += f.read()
1913 
1914  # Parse the contents of the interface file
1915  parsed_result = parser.Module.parseString(content)
1916 
1917  # Instantiate the module
1918  module = instantiator.instantiate_namespace(parsed_result)
1919 
1920  if module.name in modules:
1921  modules[
1922  module.name].content[0].content += module.content[0].content
1923  else:
1924  modules[module.name] = module
1925 
1926  for module in modules.values():
1927  # Wrap the full namespace
1928  self.wrap_namespace(module)
1929 
1930  # Generate the wrapping code (both C++ and .m files)
1931  self.generate_wrapper(module)
1932 
1933  # Generate the corresponding .m and .cpp files
1934  self.generate_content(self.content, path)
1935 
1936  return self.content
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_collector_function_upcast_from_void
def wrap_collector_function_upcast_from_void(self, class_name, func_id, cpp_name)
Definition: wrapper.py:1411
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_class_display
def wrap_class_display(self)
Definition: wrapper.py:818
gtwrap.interface_parser.function.to_cpp
str to_cpp(self)
Definition: interface_parser/function.py:56
format
std::string format(const std::string &str, const std::vector< std::string > &find, const std::vector< std::string > &replace)
Definition: openglsupport.cpp:226
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._format_varargout
def _format_varargout(cls, return_type, return_type_formatted)
Definition: wrapper.py:833
gtwrap.matlab_wrapper.mixins.FormatMixin._format_return_type
def _format_return_type(self, parser.function.ReturnType return_type, bool include_namespace=False, str separator="::")
Definition: mixins.py:167
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.get_class_name
def get_class_name(self, cls)
Definition: wrapper.py:1672
gtwrap.matlab_wrapper.mixins.CheckMixin.can_be_pointer
def can_be_pointer(self, parser.Type arg_type)
Definition: mixins.py:29
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.generate_wrapper
def generate_wrapper(self, namespace)
Definition: wrapper.py:1750
list
Definition: pytypes.h:2124
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_class_properties
def wrap_class_properties(self, str namespace_name, InstantiatedClass inst_class)
Definition: wrapper.py:761
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_collector_function_serialize
def wrap_collector_function_serialize(self, class_name, full_name='', namespace='')
Definition: wrapper.py:1832
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.ignore_classes
ignore_classes
Definition: wrapper.py:38
gtwrap.matlab_wrapper.mixins.FormatMixin
Definition: mixins.py:89
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_method
def wrap_method(self, methods)
Definition: wrapper.py:538
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrapper_id
wrapper_id
Definition: wrapper.py:70
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_collector_property_return
def wrap_collector_property_return(self, parser.Variable class_property, InstantiatedClass instantiated_class=None)
Definition: wrapper.py:1399
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._group_methods
def _group_methods(self, methods)
Definition: wrapper.py:185
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.data_type_param
data_type_param
Definition: wrapper.py:56
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_class_methods
def wrap_class_methods(self, namespace_name, inst_class, methods, serialize=(False,))
Definition: wrapper.py:844
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.generate_collector_function
def generate_collector_function(self, func_id)
Definition: wrapper.py:1419
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_methods
def wrap_methods(self, methods, global_funcs=False, global_ns=None)
Definition: wrapper.py:547
gtwrap.matlab_wrapper.templates
Definition: templates.py:1
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_collector_function_deserialize
def wrap_collector_function_deserialize(self, class_name, full_name='', namespace='')
Definition: wrapper.py:1842
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_collector_function_return_types
def wrap_collector_function_return_types(self, return_type, func_id)
Definition: wrapper.py:1240
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_enum
def wrap_enum(self, enum)
Definition: wrapper.py:1136
gtwrap.matlab_wrapper.mixins.CheckMixin
Definition: mixins.py:9
gtwrap.template_instantiator.classes
Definition: template_instantiator/classes.py:1
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.__init__
def __init__(self, module_name, top_module_namespace='', ignore_classes=(), use_boost_serialization=False)
Definition: wrapper.py:33
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._wrapper_unwrap_arguments
def _wrapper_unwrap_arguments(self, args, arg_id=0, instantiated_class=None)
Definition: wrapper.py:381
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._wrap_list_variable_arguments
def _wrap_list_variable_arguments(self, args)
Definition: wrapper.py:269
gtsam::range
Double_ range(const Point2_ &p, const Point2_ &q)
Definition: slam/expressions.h:30
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.verbose
verbose
Definition: wrapper.py:39
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_collector_function_return
def wrap_collector_function_return(self, method, instantiated_class=None)
Definition: wrapper.py:1340
gtwrap.matlab_wrapper.mixins.CheckMixin._has_serialization
def _has_serialization(self, cls)
Definition: mixins.py:23
gtwrap.matlab_wrapper.mixins.CheckMixin.is_class_enum
def is_class_enum(self, parser.Type arg_type, parser.Class class_)
Definition: mixins.py:63
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._update_wrapper_id
def _update_wrapper_id(self, collector_function=None, id_diff=0, str function_name=None)
Definition: wrapper.py:101
isinstance
bool isinstance(handle obj)
Definition: pytypes.h:825
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._wrapper_name
def _wrapper_name(self)
Definition: wrapper.py:438
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrapper_file_headers
wrapper_file_headers
Definition: wrapper.py:89
gtwrap.matlab_wrapper.mixins.FormatMixin._format_global_function
def _format_global_function(self, Union[parser.GlobalFunction, Any] function, str separator='')
Definition: mixins.py:229
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.add_class
def add_class(self, instantiated_class)
Definition: wrapper.py:95
Eigen::all
static const Eigen::internal::all_t all
Definition: IndexedViewHelper.h:171
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_class_serialize_method
def wrap_class_serialize_method(self, namespace_name, inst_class)
Definition: wrapper.py:1819
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._group_class_methods
def _group_class_methods(self, methods)
Definition: wrapper.py:828
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.class_comment
def class_comment(self, instantiated_class)
Definition: wrapper.py:467
gtwrap.interface_parser.function
Definition: interface_parser/function.py:1
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._unwrap_argument
def _unwrap_argument(self, arg, arg_id=0, instantiated_class=None)
Definition: wrapper.py:344
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._wrap_variable_arguments
def _wrap_variable_arguments(self, args, wrap_datatypes=True)
Definition: wrapper.py:224
gtwrap.matlab_wrapper.mixins.FormatMixin._format_type_name
def _format_type_name(self, parser.Typename type_name, str separator='::', bool include_namespace=True, bool is_constructor=False, bool is_method=False)
Definition: mixins.py:107
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._qualified_name
def _qualified_name(self, names)
Definition: wrapper.py:138
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.generate_content
def generate_content(self, cc_content, path)
Definition: wrapper.py:1852
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_collector_function_shared_return
def wrap_collector_function_shared_return(self, return_type_name, shared_obj, func_id, new_line=True)
Definition: wrapper.py:1225
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.generate_preamble
def generate_preamble(self)
Definition: wrapper.py:1683
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._insert_spaces
def _insert_spaces(self, x, y)
Definition: wrapper.py:141
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.use_boost_serialization
use_boost_serialization
Definition: wrapper.py:40
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_class_constructors
def wrap_class_constructors(self, namespace_name, inst_class, parent_name, ctors, is_virtual)
Definition: wrapper.py:622
gtwrap.matlab_wrapper.mixins
Definition: mixins.py:1
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_static_methods
def wrap_static_methods(self, namespace_name, instantiated_class, serialize)
Definition: wrapper.py:939
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._return_count
def _return_count(return_type)
Definition: wrapper.py:432
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.class_serialize_comment
def class_serialize_comment(self, class_name, static_methods)
Definition: wrapper.py:442
gtwrap.matlab_wrapper.mixins.FormatMixin._format_class_name
def _format_class_name(self, instantiator.InstantiatedClass instantiated_class, str separator='')
Definition: mixins.py:197
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._collector_return
def _collector_return(self, str obj, parser.Type ctype, InstantiatedClass instantiated_class=None)
Definition: wrapper.py:1273
str
Definition: pytypes.h:1524
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.module_name
module_name
Definition: wrapper.py:36
gtwrap.matlab_wrapper.wrapper.MatlabWrapper
Definition: wrapper.py:23
gtwrap.interface_parser.function.ArgumentList
Definition: interface_parser/function.py:61
gtwrap.matlab_wrapper.mixins.CheckMixin.is_ptr
def is_ptr(self, parser.Type arg_type)
Definition: mixins.py:47
gtwrap.matlab_wrapper.mixins.CheckMixin.is_enum
def is_enum(self, parser.Type arg_type, parser.Class class_)
Definition: mixins.py:83
gtwrap.matlab_wrapper.mixins.CheckMixin.is_shared_ptr
def is_shared_ptr(self, parser.Type arg_type)
Definition: mixins.py:40
gtwrap.matlab_wrapper.mixins.CheckMixin.is_ref
def is_ref(self, parser.Type arg_type)
Definition: mixins.py:54
gtwrap.template_instantiator
Definition: wrap/gtwrap/template_instantiator/__init__.py:1
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.mex_function
def mex_function(self)
Definition: wrapper.py:1635
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_namespace
def wrap_namespace(self, namespace, add_mex_file=True)
Definition: wrapper.py:1159
gtwrap.matlab_wrapper.mixins.FormatMixin._format_static_method
def _format_static_method(self, parser.StaticMethod static_method, str separator='')
Definition: mixins.py:215
gtwrap.interface_parser
Definition: wrap/gtwrap/interface_parser/__init__.py:1
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_instantiated_class
def wrap_instantiated_class(self, instantiated_class, str namespace_name='')
Definition: wrapper.py:1023
len
size_t len(handle h)
Get the length of a Python object.
Definition: pytypes.h:2399
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_global_function
def wrap_global_function(self, function)
Definition: wrapper.py:571
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._expand_default_arguments
def _expand_default_arguments(method, save_backup=True)
Definition: wrapper.py:151
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.top_module_namespace
top_module_namespace
Definition: wrapper.py:37
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.global_function_id
global_function_id
Definition: wrapper.py:82
get
Container::iterator get(Container &c, Position position)
Definition: stdlist_overload.cpp:29
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap
def wrap(self, files, path)
Definition: wrapper.py:1906
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_class_deconstructor
def wrap_class_deconstructor(self, namespace_name, inst_class)
Definition: wrapper.py:801
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._wrap_args
def _wrap_args(self, args)
Definition: wrapper.py:204
gtwrap.matlab_wrapper.mixins.FormatMixin._clean_class_name
def _clean_class_name(self, instantiator.InstantiatedClass instantiated_class)
Definition: mixins.py:97
gtwrap.matlab_wrapper.wrapper.MatlabWrapper._wrap_method_check_statement
def _wrap_method_check_statement(self, parser.ArgumentList args)
Definition: wrapper.py:290
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.data_type
data_type
Definition: wrapper.py:44
gtwrap.matlab_wrapper.wrapper.MatlabWrapper.wrap_properties_block
def wrap_properties_block(self, class_name, inst_class)
Definition: wrapper.py:726


gtsam
Author(s):
autogenerated on Tue Jun 25 2024 03:07:58