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
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/**
2012-06-27 02:52:27 +08:00
* @ file Class . cpp
2011-10-14 11:23:14 +08:00
* @ author Frank Dellaert
2012-06-27 02:52:27 +08:00
* @ author Andrew Melim
2011-10-14 02:41:56 +08:00
* */
2011-12-06 04:54:37 +08:00
# include <vector>
2011-10-14 02:41:56 +08:00
# include <iostream>
# include <fstream>
# include <boost/foreach.hpp>
2012-07-05 22:04:57 +08:00
# include <boost/lexical_cast.hpp>
2011-10-14 02:41:56 +08:00
# include "Class.h"
# include "utilities.h"
2012-06-27 02:52:27 +08:00
# include "Argument.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
/* ************************************************************************* */
2012-07-10 04:19:37 +08:00
void Class : : matlab_proxy ( const string & classFile , const string & wrapperName ,
const ReturnValue : : TypeAttributesTable & typeAttributes ,
FileWriter & wrapperFile , vector < string > & functionNames ) const {
2011-10-14 02:41:56 +08:00
// open destination classFile
2012-07-05 22:04:36 +08:00
FileWriter proxyFile ( classFile , verbose_ , " % " ) ;
2011-10-14 02:41:56 +08:00
2011-12-09 04:51:13 +08:00
// get the name of actual matlab object
2012-07-05 22:04:57 +08:00
const string matlabName = qualifiedName ( ) , cppName = qualifiedName ( " :: " ) ;
2012-07-09 08:02:43 +08:00
const string matlabBaseName = wrap : : qualifiedName ( " " , qualifiedParent ) ;
const string cppBaseName = wrap : : qualifiedName ( " :: " , qualifiedParent ) ;
2011-12-09 04:51:13 +08:00
2011-10-14 02:41:56 +08:00
// emit class proxy code
2012-03-30 13:34:23 +08:00
// we want our class to inherit the handle class for memory purposes
2012-07-08 20:27:39 +08:00
const string parent = qualifiedParent . empty ( ) ?
" handle " : : : wrap : : qualifiedName ( " " , qualifiedParent ) ;
proxyFile . oss < < " classdef " < < matlabName < < " < " < < parent < < endl ;
2012-07-05 22:04:36 +08:00
proxyFile . oss < < " properties " < < endl ;
2012-07-08 20:27:39 +08:00
proxyFile . oss < < " ptr_ " < < matlabName < < " = 0 " < < endl ;
2012-07-05 22:04:36 +08:00
proxyFile . oss < < " end " < < endl ;
proxyFile . oss < < " methods " < < endl ;
// Constructor
proxyFile . oss < < " function obj = " < < matlabName < < " (varargin) " < < endl ;
2012-07-05 22:04:57 +08:00
// Special pointer constructors - one in MATLAB to create an object and
// assign a pointer returned from a C++ function. In turn this MATLAB
// constructor calls a special C++ function that just adds the object to
// its collector. This allows wrapped functions to return objects in
// other wrap modules - to add these to their collectors the pointer is
// passed from one C++ module into matlab then back into the other C++
// module.
2012-07-05 22:04:36 +08:00
{
2012-07-05 22:04:57 +08:00
int id = functionNames . size ( ) ;
const string functionName = pointer_constructor_fragments ( proxyFile , wrapperFile , wrapperName , id ) ;
functionNames . push_back ( functionName ) ;
2012-07-05 22:04:36 +08:00
}
// Regular constructors
2012-06-27 02:52:27 +08:00
BOOST_FOREACH ( ArgumentList a , constructor . args_list )
{
2012-07-05 22:04:36 +08:00
const int id = functionNames . size ( ) ;
2012-07-09 08:02:43 +08:00
constructor . proxy_fragment ( proxyFile , wrapperName , matlabName , matlabBaseName , id , a ) ;
2012-07-05 22:04:36 +08:00
const string wrapFunctionName = constructor . wrapper_fragment ( wrapperFile ,
2012-07-09 08:02:43 +08:00
cppName , matlabName , cppBaseName , id , using_namespaces , a ) ;
2012-07-05 22:04:36 +08:00
wrapperFile . oss < < " \n " ;
functionNames . push_back ( wrapFunctionName ) ;
2011-10-14 02:41:56 +08:00
}
2012-07-05 22:04:36 +08:00
proxyFile . oss < < " else \n " ;
2012-07-05 22:05:00 +08:00
proxyFile . oss < < " error('Arguments do not match any overload of " < < matlabName < < " constructor'); " < < endl ;
2012-07-05 22:04:36 +08:00
proxyFile . oss < < " end \n " ;
2012-07-09 08:02:43 +08:00
if ( ! qualifiedParent . empty ( ) )
proxyFile . oss < < " obj = obj@ " < < matlabBaseName < < " (uint64( " < < ptr_constructor_key < < " ), base_ptr); \n " ;
proxyFile . oss < < " obj.ptr_ " < < matlabName < < " = my_ptr; \n " ;
2012-07-05 22:04:36 +08:00
proxyFile . oss < < " end \n \n " ;
// Deconstructor
{
const int id = functionNames . size ( ) ;
deconstructor . proxy_fragment ( proxyFile , wrapperName , matlabName , id ) ;
proxyFile . oss < < " \n " ;
2012-07-09 08:02:43 +08:00
const string functionName = deconstructor . wrapper_fragment ( wrapperFile , cppName , matlabName , id , using_namespaces ) ;
2012-07-05 22:04:36 +08:00
wrapperFile . oss < < " \n " ;
functionNames . push_back ( functionName ) ;
}
proxyFile . oss < < " function display(obj), obj.print(''); end \n \n " ;
proxyFile . oss < < " function disp(obj), obj.display; end \n \n " ;
// Methods
2012-07-05 22:05:00 +08:00
BOOST_FOREACH ( const Methods : : value_type & name_m , methods ) {
const Method & m = name_m . second ;
2012-07-10 04:19:37 +08:00
m . proxy_wrapper_fragments ( proxyFile , wrapperFile , cppName , matlabName , wrapperName , using_namespaces , typeAttributes , functionNames ) ;
2012-07-05 22:05:00 +08:00
proxyFile . oss < < " \n " ;
wrapperFile . oss < < " \n " ;
}
proxyFile . oss < < " end \n " ;
proxyFile . oss < < " \n " ;
proxyFile . oss < < " methods(Static = true) \n " ;
// Static methods
BOOST_FOREACH ( const StaticMethods : : value_type & name_m , static_methods ) {
const StaticMethod & m = name_m . second ;
2012-07-10 04:19:37 +08:00
m . proxy_wrapper_fragments ( proxyFile , wrapperFile , cppName , matlabName , wrapperName , using_namespaces , typeAttributes , functionNames ) ;
2012-07-05 22:04:36 +08:00
proxyFile . oss < < " \n " ;
wrapperFile . oss < < " \n " ;
}
proxyFile . oss < < " end " < < endl ;
proxyFile . oss < < " end " < < endl ;
// Close file
proxyFile . emit ( true ) ;
2011-10-14 02:41:56 +08:00
}
2011-12-06 04:54:37 +08:00
/* ************************************************************************* */
2011-12-09 04:51:13 +08:00
string Class : : qualifiedName ( const string & delim ) const {
2012-07-08 20:27:39 +08:00
return : : wrap : : qualifiedName ( delim , namespaces , name ) ;
2011-12-09 04:51:13 +08:00
}
/* ************************************************************************* */
2012-07-05 22:04:57 +08:00
string Class : : pointer_constructor_fragments ( FileWriter & proxyFile , FileWriter & wrapperFile , const string & wrapperName , int id ) const {
const string matlabName = qualifiedName ( ) , cppName = qualifiedName ( " :: " ) ;
2012-07-09 08:02:43 +08:00
const string wrapFunctionName = matlabName + " _collectorInsertAndMakeBase_ " + boost : : lexical_cast < string > ( id ) ;
const string baseMatlabName = wrap : : qualifiedName ( " " , qualifiedParent ) ;
const string baseCppName = wrap : : qualifiedName ( " :: " , qualifiedParent ) ;
2012-07-05 22:04:57 +08:00
// MATLAB constructor that assigns pointer to matlab object then calls c++
// function to add the object to the collector.
proxyFile . oss < < " if nargin == 2 && isa(varargin{1}, 'uint64') && " ;
proxyFile . oss < < " varargin{1} == uint64( " < < ptr_constructor_key < < " ) \n " ;
2012-07-09 08:02:43 +08:00
proxyFile . oss < < " my_ptr = varargin{2}; \n " ;
if ( qualifiedParent . empty ( ) ) // If this class has a base class, we'll get a base class pointer back
proxyFile . oss < < " " ;
else
proxyFile . oss < < " base_ptr = " ;
proxyFile . oss < < wrapperName < < " ( " < < id < < " , my_ptr); \n " ; // Call collector insert and get base class ptr
2012-07-05 22:04:57 +08:00
// C++ function to add pointer from MATLAB to collector. The pointer always
// comes from a C++ return value; this mechanism allows the object to be added
2012-07-09 08:02:43 +08:00
// to a collector in a different wrap module. If this class has a base class,
// a new pointer to the base class is allocated and returned.
2012-07-05 22:04:57 +08:00
wrapperFile . oss < < " void " < < wrapFunctionName < < " (int nargout, mxArray *out[], int nargin, const mxArray *in[]) " < < endl ;
wrapperFile . oss < < " { \n " ;
wrapperFile . oss < < " mexAtExit(&_deleteAllObjects); \n " ;
generateUsingNamespace ( wrapperFile , using_namespaces ) ;
// Typedef boost::shared_ptr
2012-07-09 08:02:43 +08:00
wrapperFile . oss < < " typedef boost::shared_ptr< " < < cppName < < " > Shared; \n " ;
2012-07-05 22:04:57 +08:00
wrapperFile . oss < < " \n " ;
// Get self pointer passed in
wrapperFile . oss < < " Shared *self = *reinterpret_cast<Shared**> (mxGetData(in[0])); \n " ;
// Add to collector
wrapperFile . oss < < " collector_ " < < matlabName < < " .insert(self); \n " ;
2012-07-09 08:02:43 +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)
if ( ! qualifiedParent . empty ( ) ) {
wrapperFile . oss < < " \n " ;
wrapperFile . oss < < " typedef boost::shared_ptr< " < < baseCppName < < " > SharedBase; \n " ;
wrapperFile . oss < < " out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL); \n " ;
wrapperFile . oss < < " *reinterpret_cast<SharedBase**>(mxGetData(out[0])) = new SharedBase(*self); \n " ;
}
2012-07-05 22:04:57 +08:00
wrapperFile . oss < < " } \n " ;
return wrapFunctionName ;
}
/* ************************************************************************* */