2011-10-14 02:41:56 +08:00
/* ----------------------------------------------------------------------------
* GTSAM Copyright 2010 , Georgia Tech Research Corporation ,
* Atlanta , Georgia 30332 - 0415
* All Rights Reserved
* Authors : Frank Dellaert , et al . ( see THANKS for the full author list )
* See LICENSE for the license information
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
2011-10-14 11:23:14 +08:00
* @ file Constructor . ccp
* @ author Frank Dellaert
2012-06-27 02:52:27 +08:00
* @ author Andrew Melim
2012-07-13 06:28:28 +08:00
* @ author Richard Roberts
2011-10-14 02:41:56 +08:00
* */
# include <iostream>
# include <fstream>
2012-06-27 02:52:27 +08:00
# include <algorithm>
2011-10-14 02:41:56 +08:00
2012-07-05 22:04:36 +08:00
# include <boost/lexical_cast.hpp>
2011-10-14 02:41:56 +08:00
# include "utilities.h"
# include "Constructor.h"
2016-09-10 03:52:44 +08:00
# include "Class.h"
2011-10-14 02:41:56 +08:00
using namespace std ;
2011-12-03 00:43:15 +08:00
using namespace wrap ;
2011-10-14 02:41:56 +08:00
/* ************************************************************************* */
2014-11-15 00:47:25 +08:00
string Constructor : : matlab_wrapper_name ( Str className ) const {
2012-07-03 02:18:11 +08:00
string str = " new_ " + className ;
2011-10-14 02:41:56 +08:00
return str ;
}
/* ************************************************************************* */
2014-11-15 00:47:25 +08:00
void Constructor : : proxy_fragment ( FileWriter & file ,
const std : : string & wrapperName , bool hasParent , const int id ,
const ArgumentList args ) const {
2012-10-02 22:40:07 +08:00
size_t nrArgs = args . size ( ) ;
// check for number of arguments...
2012-07-05 22:04:36 +08:00
file . oss < < " elseif nargin == " < < nrArgs ;
2014-11-15 00:47:25 +08:00
if ( nrArgs > 0 )
file . oss < < " && " ;
2012-10-02 22:40:07 +08:00
// ...and their types
2011-10-14 02:41:56 +08:00
bool first = true ;
2014-11-15 00:47:25 +08:00
for ( size_t i = 0 ; i < nrArgs ; i + + ) {
if ( ! first )
file . oss < < " && " ;
file . oss < < " isa(varargin{ " < < i + 1 < < " },' " < < args [ i ] . matlabClass ( " . " )
< < " ') " ;
first = false ;
2012-01-10 13:06:46 +08:00
}
// emit code for calling constructor
2014-11-15 00:47:25 +08:00
if ( hasParent )
2012-10-02 22:40:07 +08:00
file . oss < < " \n [ my_ptr, base_ptr ] = " ;
else
file . oss < < " \n my_ptr = " ;
2012-07-09 08:02:43 +08:00
file . oss < < wrapperName < < " ( " < < id ;
2012-01-10 13:06:46 +08:00
// emit constructor arguments
2014-11-15 00:47:25 +08:00
for ( size_t i = 0 ; i < nrArgs ; i + + ) {
2012-07-08 20:27:39 +08:00
file . oss < < " , " ;
2014-11-15 00:47:25 +08:00
file . oss < < " varargin{ " < < i + 1 < < " } " ;
2011-10-14 02:41:56 +08:00
}
2012-07-05 22:04:36 +08:00
file . oss < < " ); \n " ;
2011-10-14 02:41:56 +08:00
}
/* ************************************************************************* */
2014-11-15 00:47:25 +08:00
string Constructor : : wrapper_fragment ( FileWriter & file , Str cppClassName ,
2014-11-30 17:38:24 +08:00
Str matlabUniqueName , boost : : optional < string > cppBaseClassName , int id ,
2014-11-15 00:47:25 +08:00
const ArgumentList & al ) const {
2012-07-05 22:04:57 +08:00
2014-11-15 00:47:25 +08:00
const string wrapFunctionName = matlabUniqueName + " _constructor_ "
+ boost : : lexical_cast < string > ( id ) ;
2012-07-05 22:04:36 +08:00
2014-11-15 00:47:25 +08:00
file . oss < < " void " < < wrapFunctionName
< < " (int nargout, mxArray *out[], int nargin, const mxArray *in[]) "
< < endl ;
2012-07-05 22:04:36 +08:00
file . oss < < " { \n " ;
2012-10-02 22:40:07 +08:00
file . oss < < " mexAtExit(&_deleteAllObjects); \n " ;
2012-06-27 02:52:27 +08:00
//Typedef boost::shared_ptr
2012-10-02 22:40:07 +08:00
file . oss < < " typedef boost::shared_ptr< " < < cppClassName < < " > Shared; \n " ;
file . oss < < " \n " ;
2012-06-27 02:52:27 +08:00
2012-10-02 22:40:07 +08:00
//Check to see if there will be any arguments and remove {} for consiseness
2014-11-15 00:47:25 +08:00
if ( al . size ( ) > 0 )
2012-10-02 22:40:07 +08:00
al . matlab_unwrap ( file ) ; // unwrap arguments
2014-11-15 00:47:25 +08:00
file . oss < < " Shared *self = new Shared(new " < < cppClassName < < " ( "
< < al . names ( ) < < " )); " < < endl ;
2012-10-02 22:40:07 +08:00
file . oss < < " collector_ " < < matlabUniqueName < < " .insert(self); \n " ;
2012-07-05 22:04:36 +08:00
2014-11-15 00:47:25 +08:00
if ( verbose_ )
2013-03-16 07:24:30 +08:00
file . oss < < " std::cout << \" constructed \" << self << std::endl; " < < endl ;
2014-11-15 00:47:25 +08:00
file . oss
< < " out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL); "
< < endl ;
file . oss < < " *reinterpret_cast<Shared**> (mxGetData(out[0])) = self; "
< < endl ;
2012-06-27 02:52:27 +08:00
2012-10-02 22:40:07 +08:00
// If we have a base class, return the base class pointer (MATLAB will call the base class collectorInsertAndMakeBase to add this to the collector and recurse the heirarchy)
2014-11-30 17:38:24 +08:00
if ( cppBaseClassName ) {
2012-10-02 22:40:07 +08:00
file . oss < < " \n " ;
2014-11-30 17:38:24 +08:00
file . oss < < " typedef boost::shared_ptr< " < < * cppBaseClassName
2014-11-15 00:47:25 +08:00
< < " > SharedBase; \n " ;
file . oss
< < " out[1] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL); \n " ;
file . oss
< < " *reinterpret_cast<SharedBase**>(mxGetData(out[1])) = new SharedBase(*self); \n " ;
2012-10-02 22:40:07 +08:00
}
2012-07-09 08:02:43 +08:00
2012-01-16 05:42:41 +08:00
file . oss < < " } " < < endl ;
2011-10-14 02:41:56 +08:00
2012-10-02 22:40:07 +08:00
return wrapFunctionName ;
2011-10-14 02:41:56 +08:00
}
/* ************************************************************************* */
2014-11-15 00:47:25 +08:00
void Constructor : : python_wrapper ( FileWriter & wrapperFile , Str className ) const {
wrapperFile . oss < < " .def( \" " < < name_ < < " \" , & " < < className < < " :: " < < name_
< < " ); \n " ;
}
2016-09-11 07:44:53 +08:00
/* ************************************************************************* */
bool Constructor : : hasDefaultConstructor ( ) const {
for ( size_t i = 0 ; i < nrOverloads ( ) ; i + + ) {
if ( argumentList ( i ) . size ( ) = = 0 ) return true ;
}
return false ;
}
2014-11-15 00:47:25 +08:00
/* ************************************************************************* */
2016-09-10 00:01:51 +08:00
void Constructor : : emit_cython_pxd ( FileWriter & pxdFile , Str className ) const {
2016-09-13 06:47:04 +08:00
// HACK HACK: always add the default copy constructor by default
pxdFile . oss < < " \t \t " < < className < < " (const " < < className
< < " &) except + \n " ;
2016-09-11 07:44:53 +08:00
2016-09-09 01:33:32 +08:00
for ( size_t i = 0 ; i < nrOverloads ( ) ; i + + ) {
ArgumentList args = argumentList ( i ) ;
2016-09-13 06:17:47 +08:00
// ignore copy constructor, it's generated above by default
2016-09-11 07:44:53 +08:00
if ( args . size ( ) = = 1 & & args [ 0 ] . is_const & & args [ 0 ] . is_ref & &
2016-09-13 06:36:45 +08:00
! args [ 0 ] . is_ptr & & ( args [ 0 ] . type . cythonClass ( ) = = className | |
args [ 0 ] . type . cythonClass ( ) = = " This " ) )
2016-09-13 06:17:47 +08:00
continue ;
2016-09-11 07:44:53 +08:00
// generate the constructor
2016-09-09 01:33:32 +08:00
pxdFile . oss < < " \t \t " < < className < < " ( " ;
2016-09-12 06:14:19 +08:00
args . emit_cython_pxd ( pxdFile , className ) ;
2016-09-09 01:33:32 +08:00
pxdFile . oss < < " ) " < < " except + \n " ;
}
}
/* ************************************************************************* */
2016-09-10 03:52:44 +08:00
void Constructor : : emit_cython_pyx ( FileWriter & pyxFile , const Class & cls ) const {
// FIXME: handle overloads properly! This is lazy...
for ( size_t i = 0 ; i < nrOverloads ( ) ; i + + ) {
ArgumentList args = argumentList ( i ) ;
pyxFile . oss < < " \t @staticmethod \n " ;
2016-09-10 04:39:12 +08:00
pyxFile . oss < < " \t def __Create "
< < ( ( i > 0 ) ? to_string ( i ) : " " ) < < " __( " ;
2016-09-10 03:52:44 +08:00
args . emit_cython_pyx ( pyxFile ) ;
pyxFile . oss < < " ): \n " ;
2016-09-11 07:50:12 +08:00
// Don't use cyCreateFromValue because the class might not have
// copy constructor and copy assignment operator!!
// For example: noiseModel::Robust doesn't have the copy assignment operator
// because its members are shared_ptr to abstract base classes. That fails
// Cython to generate the object as it assigns the new obj to a temp variable.
2016-09-12 06:14:19 +08:00
pyxFile . oss < < " \t \t return " < < cls . cythonClass ( )
2016-09-11 07:50:12 +08:00
< < " .cyCreateFromShared( " < < cls . pyxSharedCythonClass ( )
< < " (new " < < cls . pyxCythonClass ( ) < < " ( " ;
2016-09-10 03:52:44 +08:00
args . emit_cython_pyx_asParams ( pyxFile ) ;
2016-09-11 07:50:12 +08:00
pyxFile . oss < < " )) "
2016-09-10 03:52:44 +08:00
< < " ) \n " ;
}
2016-09-10 00:01:51 +08:00
}
/* ************************************************************************* */