Merged from branch 'branches/wrap_mods_inheritance' into branch 'branches/wrap_mods'
commit
0e7b5b7832
76
gtsam.h
76
gtsam.h
|
@ -14,16 +14,19 @@
|
||||||
* - void
|
* - void
|
||||||
* - Any class with which be copied with boost::make_shared()
|
* - Any class with which be copied with boost::make_shared()
|
||||||
* - boost::shared_ptr of any object type
|
* - boost::shared_ptr of any object type
|
||||||
* Methods cannot return
|
<* Constructors
|
||||||
* - const references of anything
|
* - Overloads are supported
|
||||||
* Limitations on methods
|
* - A class with no constructors can be returned from other functions but not allocated directly in MATLAB
|
||||||
* - Parsing does not support overloading
|
* Methods
|
||||||
* - There can only be one method (static or otherwise) with a given name
|
|
||||||
* - Constness has no effect
|
* - Constness has no effect
|
||||||
* Methods must start with a lowercase letter
|
* - Specify by-value (not reference) return types, even if C++ method returns reference
|
||||||
* Static methods must start with a letter (upper or lowercase) and use the "static" keyword
|
* - Must start with a lowercase letter
|
||||||
* - The function generated by wrap will start with an uppercase letter, regardless
|
* - Overloads are supported
|
||||||
* Arguments to functions any of
|
* Static methods
|
||||||
|
* - Must start with a letter (upper or lowercase) and use the "static" keyword
|
||||||
|
* - The first letter will be made uppercase in the generated MATLAB interface
|
||||||
|
* - Overloads are supported
|
||||||
|
=* Arguments to functions any of
|
||||||
* - Eigen types: Matrix, Vector
|
* - Eigen types: Matrix, Vector
|
||||||
* - Eigen types and classes as an optionally const reference
|
* - Eigen types and classes as an optionally const reference
|
||||||
* - C/C++ basic types: string, bool, size_t, size_t, double, char, unsigned char
|
* - C/C++ basic types: string, bool, size_t, size_t, double, char, unsigned char
|
||||||
|
@ -47,15 +50,24 @@
|
||||||
* - All namespaces must have angle brackets: <path>
|
* - All namespaces must have angle brackets: <path>
|
||||||
* - To override, add a full include statement just before the class statement
|
* - To override, add a full include statement just before the class statement
|
||||||
* - An override include can be added for a namespace by placing it just before the namespace statement
|
* - An override include can be added for a namespace by placing it just before the namespace statement
|
||||||
* Overriding type dependency checks
|
* - Both classes and namespace accept exactly one namespace
|
||||||
|
* Using classes defined in other modules
|
||||||
* - If you are using a class 'OtherClass' not wrapped in this definition file, add "class OtherClass;" to avoid a dependency error
|
* - If you are using a class 'OtherClass' not wrapped in this definition file, add "class OtherClass;" to avoid a dependency error
|
||||||
|
* Virtual inheritance
|
||||||
|
* - Specify fully-qualified base classes, i.e. "virtual class Derived : module::Base {"
|
||||||
|
* - Mark with 'virtual' keyword, e.g. "virtual class Base {", and also "virtual class Derived : module::Base {"
|
||||||
|
* - Forward declarations must also be marked virtual, e.g. "virtual class module::Base;" and
|
||||||
|
* also "virtual class module::Derived;"
|
||||||
|
* - Pure virtual (abstract) classes should list no constructors in this interface file
|
||||||
|
* - Virtual classes must have a clone() function in C++ (though it does not have to be included
|
||||||
|
* in the MATLAB interface). clone() will be called whenever an object copy is needed, instead
|
||||||
|
* of using the copy constructor (which is used for non-virtual objects).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Status:
|
* Status:
|
||||||
* - TODO: global functions
|
* - TODO: global functions
|
||||||
* - TODO: default values for arguments
|
* - TODO: default values for arguments
|
||||||
* - TODO: signatures for constructors can be ambiguous if two types have the same first letter
|
|
||||||
* - TODO: Handle gtsam::Rot3M conversions to quaternions
|
* - TODO: Handle gtsam::Rot3M conversions to quaternions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -65,7 +77,17 @@ namespace gtsam {
|
||||||
// base
|
// base
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
class LieVector {
|
virtual class Value {
|
||||||
|
// No constructors because this is an abstract class
|
||||||
|
|
||||||
|
// Testable
|
||||||
|
void print(string s) const;
|
||||||
|
|
||||||
|
// Manifold
|
||||||
|
size_t dim() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual class LieVector : gtsam::Value {
|
||||||
// Standard constructors
|
// Standard constructors
|
||||||
LieVector();
|
LieVector();
|
||||||
LieVector(Vector v);
|
LieVector(Vector v);
|
||||||
|
@ -97,7 +119,7 @@ class LieVector {
|
||||||
// geometry
|
// geometry
|
||||||
//*************************************************************************
|
//*************************************************************************
|
||||||
|
|
||||||
class Point2 {
|
virtual class Point2 : gtsam::Value {
|
||||||
// Standard Constructors
|
// Standard Constructors
|
||||||
Point2();
|
Point2();
|
||||||
Point2(double x, double y);
|
Point2(double x, double y);
|
||||||
|
@ -129,7 +151,7 @@ class Point2 {
|
||||||
Vector vector() const;
|
Vector vector() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StereoPoint2 {
|
virtual class StereoPoint2 : gtsam::Value {
|
||||||
// Standard Constructors
|
// Standard Constructors
|
||||||
StereoPoint2();
|
StereoPoint2();
|
||||||
StereoPoint2(double uL, double uR, double v);
|
StereoPoint2(double uL, double uR, double v);
|
||||||
|
@ -158,7 +180,7 @@ class StereoPoint2 {
|
||||||
Vector vector() const;
|
Vector vector() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Point3 {
|
virtual class Point3 : gtsam::Value {
|
||||||
// Standard Constructors
|
// Standard Constructors
|
||||||
Point3();
|
Point3();
|
||||||
Point3(double x, double y, double z);
|
Point3(double x, double y, double z);
|
||||||
|
@ -191,7 +213,7 @@ class Point3 {
|
||||||
double z() const;
|
double z() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Rot2 {
|
virtual class Rot2 : gtsam::Value {
|
||||||
// Standard Constructors and Named Constructors
|
// Standard Constructors and Named Constructors
|
||||||
Rot2();
|
Rot2();
|
||||||
Rot2(double theta);
|
Rot2(double theta);
|
||||||
|
@ -233,7 +255,7 @@ class Rot2 {
|
||||||
Matrix matrix() const;
|
Matrix matrix() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Rot3 {
|
virtual class Rot3 : gtsam::Value {
|
||||||
// Standard Constructors and Named Constructors
|
// Standard Constructors and Named Constructors
|
||||||
Rot3();
|
Rot3();
|
||||||
Rot3(Matrix R);
|
Rot3(Matrix R);
|
||||||
|
@ -285,7 +307,7 @@ class Rot3 {
|
||||||
// Vector toQuaternion() const; // FIXME: Can't cast to Vector properly
|
// Vector toQuaternion() const; // FIXME: Can't cast to Vector properly
|
||||||
};
|
};
|
||||||
|
|
||||||
class Pose2 {
|
virtual class Pose2 : gtsam::Value {
|
||||||
// Standard Constructor
|
// Standard Constructor
|
||||||
Pose2();
|
Pose2();
|
||||||
Pose2(double x, double y, double theta);
|
Pose2(double x, double y, double theta);
|
||||||
|
@ -331,7 +353,7 @@ class Pose2 {
|
||||||
Matrix matrix() const;
|
Matrix matrix() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Pose3 {
|
virtual class Pose3 : gtsam::Value {
|
||||||
// Standard Constructors
|
// Standard Constructors
|
||||||
Pose3();
|
Pose3();
|
||||||
Pose3(const gtsam::Pose3& pose);
|
Pose3(const gtsam::Pose3& pose);
|
||||||
|
@ -379,7 +401,7 @@ class Pose3 {
|
||||||
double range(const gtsam::Pose3& pose); // FIXME: shadows other range
|
double range(const gtsam::Pose3& pose); // FIXME: shadows other range
|
||||||
};
|
};
|
||||||
|
|
||||||
class Cal3_S2 {
|
virtual class Cal3_S2 : gtsam::Value {
|
||||||
// Standard Constructors
|
// Standard Constructors
|
||||||
Cal3_S2();
|
Cal3_S2();
|
||||||
Cal3_S2(double fx, double fy, double s, double u0, double v0);
|
Cal3_S2(double fx, double fy, double s, double u0, double v0);
|
||||||
|
@ -429,7 +451,7 @@ class Cal3_S2Stereo {
|
||||||
double baseline() const;
|
double baseline() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CalibratedCamera {
|
virtual class CalibratedCamera : gtsam::Value {
|
||||||
// Standard Constructors and Named Constructors
|
// Standard Constructors and Named Constructors
|
||||||
CalibratedCamera();
|
CalibratedCamera();
|
||||||
CalibratedCamera(const gtsam::Pose3& pose);
|
CalibratedCamera(const gtsam::Pose3& pose);
|
||||||
|
@ -459,7 +481,7 @@ class CalibratedCamera {
|
||||||
double range(const gtsam::Point3& p) const; // TODO: Other overloaded range methods
|
double range(const gtsam::Point3& p) const; // TODO: Other overloaded range methods
|
||||||
};
|
};
|
||||||
|
|
||||||
class SimpleCamera {
|
virtual class SimpleCamera : gtsam::Value {
|
||||||
// Standard Constructors and Named Constructors
|
// Standard Constructors and Named Constructors
|
||||||
SimpleCamera();
|
SimpleCamera();
|
||||||
SimpleCamera(const gtsam::Pose3& pose);
|
SimpleCamera(const gtsam::Pose3& pose);
|
||||||
|
@ -683,14 +705,14 @@ namespace noiseModel {
|
||||||
class Base {
|
class Base {
|
||||||
};
|
};
|
||||||
|
|
||||||
class Gaussian {
|
class Gaussian : gtsam::noiseModel::Base {
|
||||||
static gtsam::noiseModel::Gaussian* SqrtInformation(Matrix R);
|
static gtsam::noiseModel::Gaussian* SqrtInformation(Matrix R);
|
||||||
static gtsam::noiseModel::Gaussian* Covariance(Matrix R);
|
static gtsam::noiseModel::Gaussian* Covariance(Matrix R);
|
||||||
// Matrix R() const; // FIXME: cannot parse!!!
|
// Matrix R() const; // FIXME: cannot parse!!!
|
||||||
void print(string s) const;
|
void print(string s) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Diagonal {
|
class Diagonal : gtsam::noiseModel::Gaussian {
|
||||||
static gtsam::noiseModel::Diagonal* Sigmas(Vector sigmas);
|
static gtsam::noiseModel::Diagonal* Sigmas(Vector sigmas);
|
||||||
static gtsam::noiseModel::Diagonal* Variances(Vector variances);
|
static gtsam::noiseModel::Diagonal* Variances(Vector variances);
|
||||||
static gtsam::noiseModel::Diagonal* Precisions(Vector precisions);
|
static gtsam::noiseModel::Diagonal* Precisions(Vector precisions);
|
||||||
|
@ -698,14 +720,14 @@ class Diagonal {
|
||||||
void print(string s) const;
|
void print(string s) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Isotropic {
|
class Isotropic : gtsam::noiseModel::Gaussian {
|
||||||
static gtsam::noiseModel::Isotropic* Sigma(size_t dim, double sigma);
|
static gtsam::noiseModel::Isotropic* Sigma(size_t dim, double sigma);
|
||||||
static gtsam::noiseModel::Isotropic* Variance(size_t dim, double varianace);
|
static gtsam::noiseModel::Isotropic* Variance(size_t dim, double varianace);
|
||||||
static gtsam::noiseModel::Isotropic* Precision(size_t dim, double precision);
|
static gtsam::noiseModel::Isotropic* Precision(size_t dim, double precision);
|
||||||
void print(string s) const;
|
void print(string s) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Unit {
|
class Unit : gtsam::noiseModel::Gaussian {
|
||||||
static gtsam::noiseModel::Unit* Create(size_t dim);
|
static gtsam::noiseModel::Unit* Create(size_t dim);
|
||||||
void print(string s) const;
|
void print(string s) const;
|
||||||
};
|
};
|
||||||
|
@ -944,7 +966,9 @@ class Values {
|
||||||
Values();
|
Values();
|
||||||
size_t size() const;
|
size_t size() const;
|
||||||
void print(string s) const;
|
void print(string s) const;
|
||||||
|
void insert(size_t j, const gtsam::Value& value);
|
||||||
bool exists(size_t j) const;
|
bool exists(size_t j) const;
|
||||||
|
gtsam::Value at(size_t j) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Actually a FastList<Key>
|
// Actually a FastList<Key>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
#include <boost/pool/singleton_pool.hpp>
|
#include <boost/pool/singleton_pool.hpp>
|
||||||
#include <gtsam/base/Value.h>
|
#include <gtsam/base/Value.h>
|
||||||
|
|
||||||
|
@ -37,7 +37,8 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a duplicate object returned as a pointer to the generic Value interface.
|
* Create a duplicate object returned as a pointer to the generic Value interface.
|
||||||
* For the sake of performance, this function use singleton pool allocator instead of the normal heap allocator
|
* For the sake of performance, this function use singleton pool allocator instead of the normal heap allocator.
|
||||||
|
* The result must be deleted with Value::deallocate_, not with the 'delete' operator.
|
||||||
*/
|
*/
|
||||||
virtual Value* clone_() const {
|
virtual Value* clone_() const {
|
||||||
void *place = boost::singleton_pool<PoolTag, sizeof(DERIVED)>::malloc();
|
void *place = boost::singleton_pool<PoolTag, sizeof(DERIVED)>::malloc();
|
||||||
|
@ -53,6 +54,13 @@ public:
|
||||||
boost::singleton_pool<PoolTag, sizeof(DERIVED)>::free((void*)this);
|
boost::singleton_pool<PoolTag, sizeof(DERIVED)>::free((void*)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone this value (normal clone on the heap, delete with 'delete' operator)
|
||||||
|
*/
|
||||||
|
virtual boost::shared_ptr<Value> clone() const {
|
||||||
|
return boost::make_shared<DERIVED>(static_cast<const DERIVED&>(*this));
|
||||||
|
}
|
||||||
|
|
||||||
/// equals implementing generic Value interface
|
/// equals implementing generic Value interface
|
||||||
virtual bool equals_(const Value& p, double tol = 1e-9) const {
|
virtual bool equals_(const Value& p, double tol = 1e-9) const {
|
||||||
// Cast the base class Value pointer to a derived class pointer
|
// Cast the base class Value pointer to a derived class pointer
|
||||||
|
|
|
@ -101,12 +101,15 @@ namespace gtsam {
|
||||||
class Value {
|
class Value {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Allocate and construct a clone of this value */
|
/** Clone this value in a special memory pool, must be deleted with Value::deallocate_, *not* with the 'delete' operator. */
|
||||||
virtual Value* clone_() const = 0;
|
virtual Value* clone_() const = 0;
|
||||||
|
|
||||||
/** Deallocate a raw pointer of this value */
|
/** Deallocate a raw pointer of this value */
|
||||||
virtual void deallocate_() const = 0;
|
virtual void deallocate_() const = 0;
|
||||||
|
|
||||||
|
/** Clone this value (normal clone on the heap, delete with 'delete' operator) */
|
||||||
|
virtual boost::shared_ptr<Value> clone() const = 0;
|
||||||
|
|
||||||
/** Compare this Value with another for equality. */
|
/** Compare this Value with another for equality. */
|
||||||
virtual bool equals_(const Value& other, double tol = 1e-9) const = 0;
|
virtual bool equals_(const Value& other, double tol = 1e-9) const = 0;
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ void Argument::matlab_unwrap(FileWriter& file, const string& matlabName) const {
|
||||||
file.oss << cppType << " " << name << " = unwrap< ";
|
file.oss << cppType << " " << name << " = unwrap< ";
|
||||||
|
|
||||||
file.oss << cppType << " >(" << matlabName;
|
file.oss << cppType << " >(" << matlabName;
|
||||||
if (is_ptr || is_ref) file.oss << ", \"" << matlabType << "\"";
|
if (is_ptr || is_ref) file.oss << ", \"ptr_" << matlabType << "\"";
|
||||||
file.oss << ");" << endl;
|
file.oss << ");" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
345
wrap/Class.cpp
345
wrap/Class.cpp
|
@ -1,168 +1,177 @@
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
|
|
||||||
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
||||||
* Atlanta, Georgia 30332-0415
|
* Atlanta, Georgia 30332-0415
|
||||||
* All Rights Reserved
|
* All Rights Reserved
|
||||||
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
||||||
|
|
||||||
* See LICENSE for the license information
|
* See LICENSE for the license information
|
||||||
|
|
||||||
* -------------------------------------------------------------------------- */
|
* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file Class.cpp
|
* @file Class.cpp
|
||||||
* @author Frank Dellaert
|
* @author Frank Dellaert
|
||||||
* @author Andrew Melim
|
* @author Andrew Melim
|
||||||
**/
|
**/
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <stdint.h>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
#include "Class.h"
|
#include "Class.h"
|
||||||
#include "utilities.h"
|
#include "utilities.h"
|
||||||
#include "Argument.h"
|
#include "Argument.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace wrap;
|
using namespace wrap;
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void Class::matlab_proxy(const string& classFile, const string& wrapperName, FileWriter& wrapperFile, vector<string>& functionNames) const {
|
void Class::matlab_proxy(const string& classFile, const string& wrapperName,
|
||||||
// open destination classFile
|
const ReturnValue::TypeAttributesTable& typeAttributes,
|
||||||
FileWriter proxyFile(classFile, verbose_, "%");
|
FileWriter& wrapperFile, vector<string>& functionNames) const {
|
||||||
|
// open destination classFile
|
||||||
// get the name of actual matlab object
|
FileWriter proxyFile(classFile, verbose_, "%");
|
||||||
const string matlabName = qualifiedName(), cppName = qualifiedName("::");
|
|
||||||
|
// get the name of actual matlab object
|
||||||
// emit class proxy code
|
const string matlabName = qualifiedName(), cppName = qualifiedName("::");
|
||||||
// we want our class to inherit the handle class for memory purposes
|
const string matlabBaseName = wrap::qualifiedName("", qualifiedParent);
|
||||||
proxyFile.oss << "classdef " << matlabName << " < handle" << endl;
|
const string cppBaseName = wrap::qualifiedName("::", qualifiedParent);
|
||||||
proxyFile.oss << " properties" << endl;
|
|
||||||
proxyFile.oss << " self = 0" << endl;
|
// emit class proxy code
|
||||||
proxyFile.oss << " end" << endl;
|
// we want our class to inherit the handle class for memory purposes
|
||||||
proxyFile.oss << " methods" << endl;
|
const string parent = qualifiedParent.empty() ?
|
||||||
|
"handle" : ::wrap::qualifiedName("", qualifiedParent);
|
||||||
// Constructor
|
proxyFile.oss << "classdef " << matlabName << " < " << parent << endl;
|
||||||
proxyFile.oss << " function obj = " << matlabName << "(varargin)" << endl;
|
proxyFile.oss << " properties" << endl;
|
||||||
// Special pointer constructors - one in MATLAB to create an object and
|
proxyFile.oss << " ptr_" << matlabName << " = 0" << endl;
|
||||||
// assign a pointer returned from a C++ function. In turn this MATLAB
|
proxyFile.oss << " end" << endl;
|
||||||
// constructor calls a special C++ function that just adds the object to
|
proxyFile.oss << " methods" << endl;
|
||||||
// its collector. This allows wrapped functions to return objects in
|
|
||||||
// other wrap modules - to add these to their collectors the pointer is
|
// Constructor
|
||||||
// passed from one C++ module into matlab then back into the other C++
|
proxyFile.oss << " function obj = " << matlabName << "(varargin)" << endl;
|
||||||
// module.
|
// Special pointer constructors - one in MATLAB to create an object and
|
||||||
{
|
// assign a pointer returned from a C++ function. In turn this MATLAB
|
||||||
int id = functionNames.size();
|
// constructor calls a special C++ function that just adds the object to
|
||||||
const string functionName = pointer_constructor_fragments(proxyFile, wrapperFile, wrapperName, id);
|
// its collector. This allows wrapped functions to return objects in
|
||||||
functionNames.push_back(functionName);
|
// 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++
|
||||||
// Regular constructors
|
// module.
|
||||||
BOOST_FOREACH(ArgumentList a, constructor.args_list)
|
{
|
||||||
{
|
int id = functionNames.size();
|
||||||
const int id = functionNames.size();
|
const string functionName = pointer_constructor_fragments(proxyFile, wrapperFile, wrapperName, id);
|
||||||
constructor.proxy_fragment(proxyFile, wrapperName, matlabName, id, a);
|
functionNames.push_back(functionName);
|
||||||
const string wrapFunctionName = constructor.wrapper_fragment(wrapperFile,
|
}
|
||||||
cppName, matlabName, id, using_namespaces, includes, a);
|
// Regular constructors
|
||||||
wrapperFile.oss << "\n";
|
BOOST_FOREACH(ArgumentList a, constructor.args_list)
|
||||||
functionNames.push_back(wrapFunctionName);
|
{
|
||||||
}
|
const int id = functionNames.size();
|
||||||
proxyFile.oss << " else\n";
|
constructor.proxy_fragment(proxyFile, wrapperName, matlabName, matlabBaseName, id, a);
|
||||||
proxyFile.oss << " error('Arguments do not match any overload of " << matlabName << " constructor');" << endl;
|
const string wrapFunctionName = constructor.wrapper_fragment(wrapperFile,
|
||||||
proxyFile.oss << " end\n";
|
cppName, matlabName, cppBaseName, id, using_namespaces, a);
|
||||||
proxyFile.oss << " end\n\n";
|
wrapperFile.oss << "\n";
|
||||||
|
functionNames.push_back(wrapFunctionName);
|
||||||
// Deconstructor
|
}
|
||||||
{
|
proxyFile.oss << " else\n";
|
||||||
const int id = functionNames.size();
|
proxyFile.oss << " error('Arguments do not match any overload of " << matlabName << " constructor');" << endl;
|
||||||
deconstructor.proxy_fragment(proxyFile, wrapperName, matlabName, id);
|
proxyFile.oss << " end\n";
|
||||||
proxyFile.oss << "\n";
|
if(!qualifiedParent.empty())
|
||||||
const string functionName = deconstructor.wrapper_fragment(wrapperFile,
|
proxyFile.oss << " obj = obj@" << matlabBaseName << "(uint64(" << ptr_constructor_key << "), base_ptr);\n";
|
||||||
cppName, matlabName, id, using_namespaces, includes);
|
proxyFile.oss << " obj.ptr_" << matlabName << " = my_ptr;\n";
|
||||||
wrapperFile.oss << "\n";
|
proxyFile.oss << " end\n\n";
|
||||||
functionNames.push_back(functionName);
|
|
||||||
}
|
// Deconstructor
|
||||||
proxyFile.oss << " function display(obj), obj.print(''); end\n\n";
|
{
|
||||||
proxyFile.oss << " function disp(obj), obj.display; end\n\n";
|
const int id = functionNames.size();
|
||||||
|
deconstructor.proxy_fragment(proxyFile, wrapperName, matlabName, id);
|
||||||
// Methods
|
proxyFile.oss << "\n";
|
||||||
BOOST_FOREACH(const Methods::value_type& name_m, methods) {
|
const string functionName = deconstructor.wrapper_fragment(wrapperFile, cppName, matlabName, id, using_namespaces);
|
||||||
const Method& m = name_m.second;
|
wrapperFile.oss << "\n";
|
||||||
m.proxy_wrapper_fragments(proxyFile, wrapperFile, cppName, matlabName, wrapperName, using_namespaces, functionNames);
|
functionNames.push_back(functionName);
|
||||||
proxyFile.oss << "\n";
|
}
|
||||||
wrapperFile.oss << "\n";
|
proxyFile.oss << " function display(obj), obj.print(''); end\n\n";
|
||||||
}
|
proxyFile.oss << " function disp(obj), obj.display; end\n\n";
|
||||||
|
|
||||||
proxyFile.oss << " end\n";
|
// Methods
|
||||||
proxyFile.oss << "\n";
|
BOOST_FOREACH(const Methods::value_type& name_m, methods) {
|
||||||
proxyFile.oss << " methods(Static = true)\n";
|
const Method& m = name_m.second;
|
||||||
|
m.proxy_wrapper_fragments(proxyFile, wrapperFile, cppName, matlabName, wrapperName, using_namespaces, typeAttributes, functionNames);
|
||||||
// Static methods
|
proxyFile.oss << "\n";
|
||||||
BOOST_FOREACH(const StaticMethods::value_type& name_m, static_methods) {
|
wrapperFile.oss << "\n";
|
||||||
const StaticMethod& m = name_m.second;
|
}
|
||||||
m.proxy_wrapper_fragments(proxyFile, wrapperFile, cppName, matlabName, wrapperName, using_namespaces, functionNames);
|
|
||||||
proxyFile.oss << "\n";
|
proxyFile.oss << " end\n";
|
||||||
wrapperFile.oss << "\n";
|
proxyFile.oss << "\n";
|
||||||
}
|
proxyFile.oss << " methods(Static = true)\n";
|
||||||
|
|
||||||
proxyFile.oss << " end" << endl;
|
// Static methods
|
||||||
proxyFile.oss << "end" << endl;
|
BOOST_FOREACH(const StaticMethods::value_type& name_m, static_methods) {
|
||||||
|
const StaticMethod& m = name_m.second;
|
||||||
// Close file
|
m.proxy_wrapper_fragments(proxyFile, wrapperFile, cppName, matlabName, wrapperName, using_namespaces, typeAttributes, functionNames);
|
||||||
proxyFile.emit(true);
|
proxyFile.oss << "\n";
|
||||||
}
|
wrapperFile.oss << "\n";
|
||||||
|
}
|
||||||
/* ************************************************************************* */
|
|
||||||
string Class::qualifiedName(const string& delim) const {
|
proxyFile.oss << " end" << endl;
|
||||||
string result;
|
proxyFile.oss << "end" << endl;
|
||||||
BOOST_FOREACH(const string& ns, namespaces)
|
|
||||||
result += ns + delim;
|
// Close file
|
||||||
return result + name;
|
proxyFile.emit(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
string Class::pointer_constructor_fragments(FileWriter& proxyFile, FileWriter& wrapperFile, const string& wrapperName, int id) const {
|
string Class::qualifiedName(const string& delim) const {
|
||||||
|
return ::wrap::qualifiedName(delim, namespaces, name);
|
||||||
static const uint64_t ptr_constructor_key =
|
}
|
||||||
(uint64_t('G') << 56) |
|
|
||||||
(uint64_t('T') << 48) |
|
/* ************************************************************************* */
|
||||||
(uint64_t('S') << 40) |
|
string Class::pointer_constructor_fragments(FileWriter& proxyFile, FileWriter& wrapperFile, const string& wrapperName, int id) const {
|
||||||
(uint64_t('A') << 32) |
|
|
||||||
(uint64_t('M') << 24) |
|
const string matlabName = qualifiedName(), cppName = qualifiedName("::");
|
||||||
(uint64_t('p') << 16) |
|
const string wrapFunctionName = matlabName + "_collectorInsertAndMakeBase_" + boost::lexical_cast<string>(id);
|
||||||
(uint64_t('t') << 8) |
|
const string baseMatlabName = wrap::qualifiedName("", qualifiedParent);
|
||||||
(uint64_t('r'));
|
const string baseCppName = wrap::qualifiedName("::", qualifiedParent);
|
||||||
|
|
||||||
const string matlabName = qualifiedName(), cppName = qualifiedName("::");
|
// MATLAB constructor that assigns pointer to matlab object then calls c++
|
||||||
const string wrapFunctionName = matlabName + "_constructor_" + boost::lexical_cast<string>(id);
|
// function to add the object to the collector.
|
||||||
|
proxyFile.oss << " if nargin == 2 && isa(varargin{1}, 'uint64') && ";
|
||||||
// MATLAB constructor that assigns pointer to matlab object then calls c++
|
proxyFile.oss << "varargin{1} == uint64(" << ptr_constructor_key << ")\n";
|
||||||
// function to add the object to the collector.
|
proxyFile.oss << " my_ptr = varargin{2};\n";
|
||||||
proxyFile.oss << " if nargin == 2 && isa(varargin{1}, 'uint64') && ";
|
if(qualifiedParent.empty()) // If this class has a base class, we'll get a base class pointer back
|
||||||
proxyFile.oss << "varargin{1} == uint64(" << ptr_constructor_key << ")\n";
|
proxyFile.oss << " ";
|
||||||
proxyFile.oss << " obj.self = varargin{2};\n";
|
else
|
||||||
proxyFile.oss << " " << wrapperName << "(obj.self);\n";
|
proxyFile.oss << " base_ptr = ";
|
||||||
|
proxyFile.oss << wrapperName << "(" << id << ", my_ptr);\n"; // Call collector insert and get base class ptr
|
||||||
// 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
|
// C++ function to add pointer from MATLAB to collector. The pointer always
|
||||||
// to a collector in a different wrap module.
|
// comes from a C++ return value; this mechanism allows the object to be added
|
||||||
wrapperFile.oss << "void " << wrapFunctionName << "(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl;
|
// to a collector in a different wrap module. If this class has a base class,
|
||||||
wrapperFile.oss << "{\n";
|
// a new pointer to the base class is allocated and returned.
|
||||||
wrapperFile.oss << " mexAtExit(&_deleteAllObjects);\n";
|
wrapperFile.oss << "void " << wrapFunctionName << "(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl;
|
||||||
generateUsingNamespace(wrapperFile, using_namespaces);
|
wrapperFile.oss << "{\n";
|
||||||
// Typedef boost::shared_ptr
|
wrapperFile.oss << " mexAtExit(&_deleteAllObjects);\n";
|
||||||
wrapperFile.oss << " typedef boost::shared_ptr<" << cppName << "> Shared;\n";
|
generateUsingNamespace(wrapperFile, using_namespaces);
|
||||||
wrapperFile.oss << "\n";
|
// Typedef boost::shared_ptr
|
||||||
// Get self pointer passed in
|
wrapperFile.oss << " typedef boost::shared_ptr<" << cppName << "> Shared;\n";
|
||||||
wrapperFile.oss << " Shared *self = *reinterpret_cast<Shared**> (mxGetData(in[0]));\n";
|
wrapperFile.oss << "\n";
|
||||||
// Add to collector
|
// Get self pointer passed in
|
||||||
wrapperFile.oss << " collector_" << matlabName << ".insert(self);\n";
|
wrapperFile.oss << " Shared *self = *reinterpret_cast<Shared**> (mxGetData(in[0]));\n";
|
||||||
wrapperFile.oss << "}\n";
|
// Add to collector
|
||||||
|
wrapperFile.oss << " collector_" << matlabName << ".insert(self);\n";
|
||||||
return wrapFunctionName;
|
// 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";
|
||||||
|
}
|
||||||
|
wrapperFile.oss << "}\n";
|
||||||
|
|
||||||
|
return wrapFunctionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -34,10 +34,12 @@ struct Class {
|
||||||
typedef std::map<std::string, StaticMethod> StaticMethods;
|
typedef std::map<std::string, StaticMethod> StaticMethods;
|
||||||
|
|
||||||
/// Constructor creates an empty class
|
/// Constructor creates an empty class
|
||||||
Class(bool verbose=true) : verbose_(verbose) {}
|
Class(bool verbose=true) : verbose_(verbose), isVirtual(false) {}
|
||||||
|
|
||||||
// Then the instance variables are set directly by the Module constructor
|
// Then the instance variables are set directly by the Module constructor
|
||||||
std::string name; ///< Class name
|
std::string name; ///< Class name
|
||||||
|
bool isVirtual; ///< Whether the class is part of a virtual inheritance chain
|
||||||
|
std::vector<std::string> qualifiedParent; ///< The *single* parent - the last string is the parent class name, preceededing elements are a namespace stack
|
||||||
Methods methods; ///< Class methods
|
Methods methods; ///< Class methods
|
||||||
StaticMethods static_methods; ///< Static methods
|
StaticMethods static_methods; ///< Static methods
|
||||||
std::vector<std::string> namespaces; ///< Stack of namespaces
|
std::vector<std::string> namespaces; ///< Stack of namespaces
|
||||||
|
@ -48,7 +50,7 @@ struct Class {
|
||||||
bool verbose_; ///< verbose flag
|
bool verbose_; ///< verbose flag
|
||||||
|
|
||||||
// And finally MATLAB code is emitted, methods below called by Module::matlab_code
|
// And finally MATLAB code is emitted, methods below called by Module::matlab_code
|
||||||
void matlab_proxy(const std::string& classFile, const std::string& wrapperName,
|
void matlab_proxy(const std::string& classFile, const std::string& wrapperName, const ReturnValue::TypeAttributesTable& typeAttributes,
|
||||||
FileWriter& wrapperFile, std::vector<std::string>& functionNames) const; ///< emit proxy class
|
FileWriter& wrapperFile, std::vector<std::string>& functionNames) const; ///< emit proxy class
|
||||||
std::string qualifiedName(const std::string& delim = "") const; ///< creates a namespace-qualified name, optional delimiter
|
std::string qualifiedName(const std::string& delim = "") const; ///< creates a namespace-qualified name, optional delimiter
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ string Constructor::matlab_wrapper_name(const string& className) const {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
void Constructor::proxy_fragment(FileWriter& file, const std::string& wrapperName,
|
void Constructor::proxy_fragment(FileWriter& file, const std::string& wrapperName,
|
||||||
const string& className, const int id, const ArgumentList args) const {
|
const string& matlabName, const string& matlabBaseName, const int id, const ArgumentList args) const {
|
||||||
size_t nrArgs = args.size();
|
size_t nrArgs = args.size();
|
||||||
// check for number of arguments...
|
// check for number of arguments...
|
||||||
file.oss << " elseif nargin == " << nrArgs;
|
file.oss << " elseif nargin == " << nrArgs;
|
||||||
|
@ -50,10 +50,14 @@ void Constructor::proxy_fragment(FileWriter& file, const std::string& wrapperNam
|
||||||
first=false;
|
first=false;
|
||||||
}
|
}
|
||||||
// emit code for calling constructor
|
// emit code for calling constructor
|
||||||
file.oss << "\n obj.self = " << wrapperName << "(" << id;
|
if(matlabBaseName.empty())
|
||||||
|
file.oss << "\n my_ptr = ";
|
||||||
|
else
|
||||||
|
file.oss << "\n [ my_ptr, base_ptr ] = ";
|
||||||
|
file.oss << wrapperName << "(" << id;
|
||||||
// emit constructor arguments
|
// emit constructor arguments
|
||||||
for(size_t i=0;i<nrArgs;i++) {
|
for(size_t i=0;i<nrArgs;i++) {
|
||||||
file.oss << ",";
|
file.oss << ", ";
|
||||||
file.oss << "varargin{" << i+1 << "}";
|
file.oss << "varargin{" << i+1 << "}";
|
||||||
}
|
}
|
||||||
file.oss << ");\n";
|
file.oss << ");\n";
|
||||||
|
@ -63,9 +67,9 @@ void Constructor::proxy_fragment(FileWriter& file, const std::string& wrapperNam
|
||||||
string Constructor::wrapper_fragment(FileWriter& file,
|
string Constructor::wrapper_fragment(FileWriter& file,
|
||||||
const string& cppClassName,
|
const string& cppClassName,
|
||||||
const string& matlabClassName,
|
const string& matlabClassName,
|
||||||
|
const string& cppBaseClassName,
|
||||||
int id,
|
int id,
|
||||||
const vector<string>& using_namespaces,
|
const vector<string>& using_namespaces,
|
||||||
const vector<string>& includes,
|
|
||||||
const ArgumentList& al) const {
|
const ArgumentList& al) const {
|
||||||
|
|
||||||
const string wrapFunctionName = matlabClassName + "_constructor_" + boost::lexical_cast<string>(id);
|
const string wrapFunctionName = matlabClassName + "_constructor_" + boost::lexical_cast<string>(id);
|
||||||
|
@ -89,6 +93,14 @@ string Constructor::wrapper_fragment(FileWriter& file,
|
||||||
file.oss << " out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);" << endl;
|
file.oss << " out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);" << endl;
|
||||||
file.oss << " *reinterpret_cast<Shared**> (mxGetData(out[0])) = self;" << endl;
|
file.oss << " *reinterpret_cast<Shared**> (mxGetData(out[0])) = self;" << endl;
|
||||||
|
|
||||||
|
// 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(!cppBaseClassName.empty()) {
|
||||||
|
file.oss << "\n";
|
||||||
|
file.oss << " typedef boost::shared_ptr<" << cppBaseClassName << "> 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";
|
||||||
|
}
|
||||||
|
|
||||||
file.oss << "}" << endl;
|
file.oss << "}" << endl;
|
||||||
|
|
||||||
return wrapFunctionName;
|
return wrapFunctionName;
|
||||||
|
|
|
@ -49,16 +49,16 @@ struct Constructor {
|
||||||
* if nargin == 2, obj.self = new_Pose3_RP(varargin{1},varargin{2}); end
|
* if nargin == 2, obj.self = new_Pose3_RP(varargin{1},varargin{2}); end
|
||||||
*/
|
*/
|
||||||
void proxy_fragment(FileWriter& file, const std::string& wrapperName,
|
void proxy_fragment(FileWriter& file, const std::string& wrapperName,
|
||||||
const std::string& className, const int id,
|
const std::string& className, const std::string& matlabBaseName, const int id,
|
||||||
const ArgumentList args) const;
|
const ArgumentList args) const;
|
||||||
|
|
||||||
/// cpp wrapper
|
/// cpp wrapper
|
||||||
std::string wrapper_fragment(FileWriter& file,
|
std::string wrapper_fragment(FileWriter& file,
|
||||||
const std::string& cppClassName,
|
const std::string& cppClassName,
|
||||||
const std::string& matlabClassName,
|
const std::string& matlabClassName,
|
||||||
|
const std::string& cppBaseClassName,
|
||||||
int id,
|
int id,
|
||||||
const std::vector<std::string>& using_namespaces,
|
const std::vector<std::string>& using_namespaces,
|
||||||
const std::vector<std::string>& includes,
|
|
||||||
const ArgumentList& al) const;
|
const ArgumentList& al) const;
|
||||||
|
|
||||||
/// constructor function
|
/// constructor function
|
||||||
|
|
|
@ -39,7 +39,7 @@ void Deconstructor::proxy_fragment(FileWriter& file,
|
||||||
const std::string& qualifiedMatlabName, int id) const {
|
const std::string& qualifiedMatlabName, int id) const {
|
||||||
|
|
||||||
file.oss << " function delete(obj)\n";
|
file.oss << " function delete(obj)\n";
|
||||||
file.oss << " " << wrapperName << "(" << id << ", obj.self);\n";
|
file.oss << " " << wrapperName << "(" << id << ", obj.ptr_" << qualifiedMatlabName << ");\n";
|
||||||
file.oss << " end\n";
|
file.oss << " end\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ string Deconstructor::wrapper_fragment(FileWriter& file,
|
||||||
const string& cppClassName,
|
const string& cppClassName,
|
||||||
const string& matlabClassName,
|
const string& matlabClassName,
|
||||||
int id,
|
int id,
|
||||||
const vector<string>& using_namespaces, const vector<string>& includes) const {
|
const vector<string>& using_namespaces) const {
|
||||||
|
|
||||||
const string matlabName = matlab_wrapper_name(matlabClassName);
|
const string matlabName = matlab_wrapper_name(matlabClassName);
|
||||||
|
|
||||||
|
|
|
@ -55,8 +55,7 @@ struct Deconstructor {
|
||||||
const std::string& cppClassName,
|
const std::string& cppClassName,
|
||||||
const std::string& matlabClassName,
|
const std::string& matlabClassName,
|
||||||
int id,
|
int id,
|
||||||
const std::vector<std::string>& using_namespaces,
|
const std::vector<std::string>& using_namespaces) const;
|
||||||
const std::vector<std::string>& includes) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // \namespace wrap
|
} // \namespace wrap
|
||||||
|
|
|
@ -41,9 +41,10 @@ void Method::proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperF
|
||||||
const string& matlabClassName,
|
const string& matlabClassName,
|
||||||
const string& wrapperName,
|
const string& wrapperName,
|
||||||
const vector<string>& using_namespaces,
|
const vector<string>& using_namespaces,
|
||||||
|
const ReturnValue::TypeAttributesTable& typeAttributes,
|
||||||
vector<string>& functionNames) const {
|
vector<string>& functionNames) const {
|
||||||
|
|
||||||
proxyFile.oss << " function varargout = " << name << "(self, varargin)\n";
|
proxyFile.oss << " function varargout = " << name << "(this, varargin)\n";
|
||||||
|
|
||||||
for(size_t overload = 0; overload < argLists.size(); ++overload) {
|
for(size_t overload = 0; overload < argLists.size(); ++overload) {
|
||||||
const ArgumentList& args = argLists[overload];
|
const ArgumentList& args = argLists[overload];
|
||||||
|
@ -74,12 +75,12 @@ void Method::proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperF
|
||||||
output = "";
|
output = "";
|
||||||
else
|
else
|
||||||
output = "varargout{1} = ";
|
output = "varargout{1} = ";
|
||||||
proxyFile.oss << " " << output << wrapperName << "(" << id << ", self, varargin{:});\n";
|
proxyFile.oss << " " << output << wrapperName << "(" << id << ", this, varargin{:});\n";
|
||||||
|
|
||||||
// Output C++ wrapper code
|
// Output C++ wrapper code
|
||||||
|
|
||||||
const string wrapFunctionName = wrapper_fragment(
|
const string wrapFunctionName = wrapper_fragment(
|
||||||
wrapperFile, cppClassName, matlabClassName, overload, id, using_namespaces);
|
wrapperFile, cppClassName, matlabClassName, overload, id, using_namespaces, typeAttributes);
|
||||||
|
|
||||||
// Add to function list
|
// Add to function list
|
||||||
functionNames.push_back(wrapFunctionName);
|
functionNames.push_back(wrapFunctionName);
|
||||||
|
@ -100,7 +101,8 @@ string Method::wrapper_fragment(FileWriter& file,
|
||||||
const string& matlabClassName,
|
const string& matlabClassName,
|
||||||
int overload,
|
int overload,
|
||||||
int id,
|
int id,
|
||||||
const vector<string>& using_namespaces) const {
|
const vector<string>& using_namespaces,
|
||||||
|
const ReturnValue::TypeAttributesTable& typeAttributes) const {
|
||||||
|
|
||||||
// generate code
|
// generate code
|
||||||
|
|
||||||
|
@ -135,20 +137,16 @@ string Method::wrapper_fragment(FileWriter& file,
|
||||||
|
|
||||||
// get class pointer
|
// get class pointer
|
||||||
// example: shared_ptr<Test> = unwrap_shared_ptr< Test >(in[0], "Test");
|
// example: shared_ptr<Test> = unwrap_shared_ptr< Test >(in[0], "Test");
|
||||||
file.oss << " Shared obj = unwrap_shared_ptr<" << cppClassName << ">(in[0], \"" << cppClassName << "\");" << endl;
|
file.oss << " Shared obj = unwrap_shared_ptr<" << cppClassName << ">(in[0], \"ptr_" << matlabClassName << "\");" << endl;
|
||||||
// unwrap arguments, see Argument.cpp
|
// unwrap arguments, see Argument.cpp
|
||||||
args.matlab_unwrap(file,1);
|
args.matlab_unwrap(file,1);
|
||||||
|
|
||||||
// call method
|
// call method and wrap result
|
||||||
// example: bool result = self->return_field(t);
|
// example: out[0]=wrap<bool>(self->return_field(t));
|
||||||
file.oss << " ";
|
|
||||||
if (returnVal.type1!="void")
|
if (returnVal.type1!="void")
|
||||||
file.oss << returnVal.return_type(true,ReturnValue::pair) << " result = ";
|
returnVal.wrap_result("obj->"+name+"("+args.names()+")", file, typeAttributes);
|
||||||
file.oss << "obj->" << name << "(" << args.names() << ");\n";
|
else
|
||||||
|
file.oss << " obj->"+name+"("+args.names()+");\n";
|
||||||
// wrap result
|
|
||||||
// example: out[0]=wrap<bool>(result);
|
|
||||||
returnVal.wrap_result(file);
|
|
||||||
|
|
||||||
// finish
|
// finish
|
||||||
file.oss << "}\n";
|
file.oss << "}\n";
|
||||||
|
|
|
@ -50,6 +50,7 @@ struct Method {
|
||||||
void proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperFile,
|
void proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperFile,
|
||||||
const std::string& cppClassName, const std::string& matlabClassName,
|
const std::string& cppClassName, const std::string& matlabClassName,
|
||||||
const std::string& wrapperName, const std::vector<std::string>& using_namespaces,
|
const std::string& wrapperName, const std::vector<std::string>& using_namespaces,
|
||||||
|
const ReturnValue::TypeAttributesTable& typeAttributes,
|
||||||
std::vector<std::string>& functionNames) const;
|
std::vector<std::string>& functionNames) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -58,7 +59,8 @@ private:
|
||||||
const std::string& matlabClassname,
|
const std::string& matlabClassname,
|
||||||
int overload,
|
int overload,
|
||||||
int id,
|
int id,
|
||||||
const std::vector<std::string>& using_namespaces) const; ///< cpp wrapper
|
const std::vector<std::string>& using_namespaces,
|
||||||
|
const ReturnValue::TypeAttributesTable& typeAttributes) const; ///< cpp wrapper
|
||||||
};
|
};
|
||||||
|
|
||||||
} // \namespace wrap
|
} // \namespace wrap
|
||||||
|
|
|
@ -24,8 +24,10 @@
|
||||||
//#define BOOST_SPIRIT_DEBUG
|
//#define BOOST_SPIRIT_DEBUG
|
||||||
#include <boost/spirit/include/classic_confix.hpp>
|
#include <boost/spirit/include/classic_confix.hpp>
|
||||||
#include <boost/spirit/include/classic_clear_actor.hpp>
|
#include <boost/spirit/include/classic_clear_actor.hpp>
|
||||||
|
#include <boost/spirit/include/classic_insert_at_actor.hpp>
|
||||||
#include <boost/lambda/bind.hpp>
|
#include <boost/lambda/bind.hpp>
|
||||||
#include <boost/lambda/lambda.hpp>
|
#include <boost/lambda/lambda.hpp>
|
||||||
|
#include <boost/lambda/construct.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
@ -65,12 +67,12 @@ Module::Module(const string& interfacePath,
|
||||||
//Method method0(enable_verbose), method(enable_verbose);
|
//Method method0(enable_verbose), method(enable_verbose);
|
||||||
StaticMethod static_method0(enable_verbose), static_method(enable_verbose);
|
StaticMethod static_method0(enable_verbose), static_method(enable_verbose);
|
||||||
Class cls0(enable_verbose),cls(enable_verbose);
|
Class cls0(enable_verbose),cls(enable_verbose);
|
||||||
|
ForwardDeclaration fwDec0, fwDec;
|
||||||
vector<string> namespaces, /// current namespace tag
|
vector<string> namespaces, /// current namespace tag
|
||||||
namespace_includes, /// current set of includes
|
namespace_includes, /// current set of includes
|
||||||
namespaces_return, /// namespace for current return type
|
namespaces_return, /// namespace for current return type
|
||||||
using_namespace_current; /// All namespaces from "using" declarations
|
using_namespace_current; /// All namespaces from "using" declarations
|
||||||
string include_path = "";
|
string include_path = "";
|
||||||
string class_name = "";
|
|
||||||
const string null_str = "";
|
const string null_str = "";
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -93,7 +95,7 @@ Module::Module(const string& interfacePath,
|
||||||
Rule eigenType_p =
|
Rule eigenType_p =
|
||||||
(str_p("Vector") | "Matrix");
|
(str_p("Vector") | "Matrix");
|
||||||
|
|
||||||
Rule className_p = (lexeme_d[upper_p >> *(alnum_p | '_')] - eigenType_p - keywords_p)[assign_a(class_name)];
|
Rule className_p = (lexeme_d[upper_p >> *(alnum_p | '_')] - eigenType_p - keywords_p);
|
||||||
|
|
||||||
Rule namespace_name_p = lexeme_d[lower_p >> *(alnum_p | '_')] - keywords_p;
|
Rule namespace_name_p = lexeme_d[lower_p >> *(alnum_p | '_')] - keywords_p;
|
||||||
|
|
||||||
|
@ -114,6 +116,10 @@ Module::Module(const string& interfacePath,
|
||||||
className_p[assign_a(arg.type)] >>
|
className_p[assign_a(arg.type)] >>
|
||||||
(ch_p('*')[assign_a(arg.is_ptr,true)] | ch_p('&')[assign_a(arg.is_ref,true)]);
|
(ch_p('*')[assign_a(arg.is_ptr,true)] | ch_p('&')[assign_a(arg.is_ref,true)]);
|
||||||
|
|
||||||
|
Rule classParent_p =
|
||||||
|
*(namespace_name_p[push_back_a(cls.qualifiedParent)] >> str_p("::")) >>
|
||||||
|
className_p[push_back_a(cls.qualifiedParent)];
|
||||||
|
|
||||||
Rule name_p = lexeme_d[alpha_p >> *(alnum_p | '_')];
|
Rule name_p = lexeme_d[alpha_p >> *(alnum_p | '_')];
|
||||||
|
|
||||||
Rule argument_p =
|
Rule argument_p =
|
||||||
|
@ -196,9 +202,10 @@ Module::Module(const string& interfacePath,
|
||||||
|
|
||||||
Rule class_p =
|
Rule class_p =
|
||||||
(!*include_p
|
(!*include_p
|
||||||
|
>> !(str_p("virtual")[assign_a(cls.isVirtual, true)])
|
||||||
>> str_p("class")[push_back_a(cls.includes, include_path)][assign_a(include_path, null_str)]
|
>> str_p("class")[push_back_a(cls.includes, include_path)][assign_a(include_path, null_str)]
|
||||||
>> className_p[assign_a(cls.name)]
|
>> className_p[assign_a(cls.name)]
|
||||||
>> '{'
|
>> ((':' >> classParent_p >> '{') | '{') // By having (parent >> '{' | '{') here instead of (!parent >> '{'), we trigger a parse error on a badly-formed parent spec
|
||||||
>> *(functions_p | comments_p)
|
>> *(functions_p | comments_p)
|
||||||
>> str_p("};"))
|
>> str_p("};"))
|
||||||
[assign_a(constructor.name, cls.name)]
|
[assign_a(constructor.name, cls.name)]
|
||||||
|
@ -208,7 +215,7 @@ Module::Module(const string& interfacePath,
|
||||||
[append_a(cls.includes, namespace_includes)]
|
[append_a(cls.includes, namespace_includes)]
|
||||||
[assign_a(deconstructor.name,cls.name)]
|
[assign_a(deconstructor.name,cls.name)]
|
||||||
[assign_a(cls.deconstructor, deconstructor)]
|
[assign_a(cls.deconstructor, deconstructor)]
|
||||||
[push_back_a(classes,cls)]
|
[push_back_a(classes, cls)]
|
||||||
[assign_a(deconstructor,deconstructor0)]
|
[assign_a(deconstructor,deconstructor0)]
|
||||||
[assign_a(constructor, constructor0)]
|
[assign_a(constructor, constructor0)]
|
||||||
[assign_a(cls,cls0)];
|
[assign_a(cls,cls0)];
|
||||||
|
@ -229,9 +236,12 @@ Module::Module(const string& interfacePath,
|
||||||
>> namespace_name_p[push_back_a(using_namespace_current)] >> ch_p(';');
|
>> namespace_name_p[push_back_a(using_namespace_current)] >> ch_p(';');
|
||||||
|
|
||||||
Rule forward_declaration_p =
|
Rule forward_declaration_p =
|
||||||
str_p("class") >>
|
!(str_p("virtual")[assign_a(fwDec.isVirtual, true)])
|
||||||
(*(namespace_name_p >> str_p("::")) >> className_p)[push_back_a(forward_declarations)]
|
>> str_p("class")
|
||||||
>> ch_p(';');
|
>> (*(namespace_name_p >> str_p("::")) >> className_p)[assign_a(fwDec.name)]
|
||||||
|
>> ch_p(';')
|
||||||
|
[push_back_a(forward_declarations, fwDec)]
|
||||||
|
[assign_a(fwDec, fwDec0)];
|
||||||
|
|
||||||
Rule module_content_p = comments_p | using_namespace_p | class_p | forward_declaration_p | namespace_def_p ;
|
Rule module_content_p = comments_p | using_namespace_p | class_p | forward_declaration_p | namespace_def_p ;
|
||||||
|
|
||||||
|
@ -321,7 +331,10 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
|
||||||
wrapperFile.oss << "\n";
|
wrapperFile.oss << "\n";
|
||||||
|
|
||||||
// Dependency check list
|
// Dependency check list
|
||||||
vector<string> validTypes = forward_declarations;
|
vector<string> validTypes;
|
||||||
|
BOOST_FOREACH(const ForwardDeclaration& fwDec, forward_declarations) {
|
||||||
|
validTypes.push_back(fwDec.name);
|
||||||
|
}
|
||||||
validTypes.push_back("void");
|
validTypes.push_back("void");
|
||||||
validTypes.push_back("string");
|
validTypes.push_back("string");
|
||||||
validTypes.push_back("int");
|
validTypes.push_back("int");
|
||||||
|
@ -333,18 +346,31 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
|
||||||
validTypes.push_back("Vector");
|
validTypes.push_back("Vector");
|
||||||
validTypes.push_back("Matrix");
|
validTypes.push_back("Matrix");
|
||||||
//Create a list of parsed classes for dependency checking
|
//Create a list of parsed classes for dependency checking
|
||||||
BOOST_FOREACH(Class cls, classes) {
|
BOOST_FOREACH(const Class& cls, classes) {
|
||||||
validTypes.push_back(cls.qualifiedName("::"));
|
validTypes.push_back(cls.qualifiedName("::"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create type attributes table
|
||||||
|
ReturnValue::TypeAttributesTable typeAttributes;
|
||||||
|
BOOST_FOREACH(const ForwardDeclaration& fwDec, forward_declarations) {
|
||||||
|
if(!typeAttributes.insert(make_pair(fwDec.name, ReturnValue::TypeAttributes(fwDec.isVirtual))).second)
|
||||||
|
throw DuplicateDefinition("class " + fwDec.name);
|
||||||
|
}
|
||||||
|
BOOST_FOREACH(const Class& cls, classes) {
|
||||||
|
if(!typeAttributes.insert(make_pair(cls.qualifiedName("::"), ReturnValue::TypeAttributes(cls.isVirtual))).second)
|
||||||
|
throw DuplicateDefinition("class " + cls.qualifiedName("::"));
|
||||||
|
|
||||||
|
// Check that class is virtual if it has a parent
|
||||||
|
}
|
||||||
|
|
||||||
// Generate all includes
|
// Generate all includes
|
||||||
BOOST_FOREACH(Class cls, classes) {
|
BOOST_FOREACH(const Class& cls, classes) {
|
||||||
generateIncludes(wrapperFile, cls.name, cls.includes);
|
generateIncludes(wrapperFile, cls.name, cls.includes);
|
||||||
}
|
}
|
||||||
wrapperFile.oss << "\n";
|
wrapperFile.oss << "\n";
|
||||||
|
|
||||||
// Generate all collectors
|
// Generate all collectors
|
||||||
BOOST_FOREACH(Class cls, classes) {
|
BOOST_FOREACH(const Class& cls, classes) {
|
||||||
const string matlabName = cls.qualifiedName(), cppName = cls.qualifiedName("::");
|
const string matlabName = cls.qualifiedName(), cppName = cls.qualifiedName("::");
|
||||||
wrapperFile.oss << "typedef std::set<boost::shared_ptr<" << cppName << ">*> "
|
wrapperFile.oss << "typedef std::set<boost::shared_ptr<" << cppName << ">*> "
|
||||||
<< "Collector_" << matlabName << ";\n";
|
<< "Collector_" << matlabName << ";\n";
|
||||||
|
@ -355,7 +381,7 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
|
||||||
// generate mexAtExit cleanup function
|
// generate mexAtExit cleanup function
|
||||||
wrapperFile.oss << "void _deleteAllObjects()\n";
|
wrapperFile.oss << "void _deleteAllObjects()\n";
|
||||||
wrapperFile.oss << "{\n";
|
wrapperFile.oss << "{\n";
|
||||||
BOOST_FOREACH(Class cls, classes) {
|
BOOST_FOREACH(const Class& cls, classes) {
|
||||||
const string matlabName = cls.qualifiedName();
|
const string matlabName = cls.qualifiedName();
|
||||||
const string cppName = cls.qualifiedName("::");
|
const string cppName = cls.qualifiedName("::");
|
||||||
const string collectorType = "Collector_" + matlabName;
|
const string collectorType = "Collector_" + matlabName;
|
||||||
|
@ -369,10 +395,10 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
|
||||||
wrapperFile.oss << "}\n";
|
wrapperFile.oss << "}\n";
|
||||||
|
|
||||||
// generate proxy classes and wrappers
|
// generate proxy classes and wrappers
|
||||||
BOOST_FOREACH(Class cls, classes) {
|
BOOST_FOREACH(const Class& cls, classes) {
|
||||||
// create proxy class and wrapper code
|
// create proxy class and wrapper code
|
||||||
string classFile = toolboxPath + "/" + cls.qualifiedName() + ".m";
|
string classFile = toolboxPath + "/" + cls.qualifiedName() + ".m";
|
||||||
cls.matlab_proxy(classFile, wrapperName, wrapperFile, functionNames);
|
cls.matlab_proxy(classFile, wrapperName, typeAttributes, wrapperFile, functionNames);
|
||||||
|
|
||||||
// verify all of the function arguments
|
// verify all of the function arguments
|
||||||
//TODO:verifyArguments<ArgumentList>(validTypes, cls.constructor.args_list);
|
//TODO:verifyArguments<ArgumentList>(validTypes, cls.constructor.args_list);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "Class.h"
|
#include "Class.h"
|
||||||
|
|
||||||
|
@ -28,11 +29,18 @@ namespace wrap {
|
||||||
* A module just has a name and a list of classes
|
* A module just has a name and a list of classes
|
||||||
*/
|
*/
|
||||||
struct Module {
|
struct Module {
|
||||||
|
|
||||||
|
struct ForwardDeclaration {
|
||||||
|
std::string name;
|
||||||
|
bool isVirtual;
|
||||||
|
ForwardDeclaration() : isVirtual(false) {}
|
||||||
|
};
|
||||||
|
|
||||||
std::string name; ///< module name
|
std::string name; ///< module name
|
||||||
std::vector<Class> classes; ///< list of classes
|
std::vector<Class> classes; ///< list of classes
|
||||||
bool verbose; ///< verbose flag
|
bool verbose; ///< verbose flag
|
||||||
// std::vector<std::string> using_namespaces; ///< all default namespaces
|
// std::vector<std::string> using_namespaces; ///< all default namespaces
|
||||||
std::vector<std::string> forward_declarations;
|
std::vector<ForwardDeclaration> forward_declarations;
|
||||||
|
|
||||||
/// constructor that parses interface file
|
/// constructor that parses interface file
|
||||||
Module(const std::string& interfacePath,
|
Module(const std::string& interfacePath,
|
||||||
|
|
|
@ -46,45 +46,60 @@ string ReturnValue::qualifiedType2(const string& delim) const {
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
//TODO:Fix this
|
//TODO:Fix this
|
||||||
void ReturnValue::wrap_result(FileWriter& file) const {
|
void ReturnValue::wrap_result(const string& result, FileWriter& file, const TypeAttributesTable& typeAttributes) const {
|
||||||
string cppType1 = qualifiedType1("::"), matlabType1 = qualifiedType1();
|
string cppType1 = qualifiedType1("::"), matlabType1 = qualifiedType1();
|
||||||
string cppType2 = qualifiedType2("::"), matlabType2 = qualifiedType2();
|
string cppType2 = qualifiedType2("::"), matlabType2 = qualifiedType2();
|
||||||
|
|
||||||
if (isPair) {
|
if (isPair) {
|
||||||
// first return value in pair
|
// first return value in pair
|
||||||
if (isPtr1) {// if we already have a pointer
|
if (isPtr1) {// if we already have a pointer
|
||||||
file.oss << " Shared" << type1 <<"* ret = new Shared" << type1 << "(result.first);" << endl;
|
file.oss << " Shared" << type1 <<"* ret = new Shared" << type1 << "(" << result << ".first);" << endl;
|
||||||
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\");\n";
|
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\");\n";
|
||||||
}
|
}
|
||||||
else if (category1 == ReturnValue::CLASS) { // if we are going to make one
|
else if (category1 == ReturnValue::CLASS) { // if we are going to make one
|
||||||
file.oss << " Shared" << type1 << "* ret = new Shared" << type1 << "(new " << cppType1 << "(result.first));\n";
|
string objCopy;
|
||||||
|
if(typeAttributes.at(cppType1).isVirtual)
|
||||||
|
objCopy = "boost::dynamic_pointer_cast<" + cppType1 + ">(" + result + ".first.clone())";
|
||||||
|
else
|
||||||
|
objCopy = "new " + cppType1 + "(" + result + ".first)";
|
||||||
|
file.oss << " Shared" << type1 << "* ret = new Shared" << type1 << "(" << objCopy << ");\n";
|
||||||
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\");\n";
|
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\");\n";
|
||||||
}
|
}
|
||||||
else // if basis type
|
else // if basis type
|
||||||
file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(result.first);\n";
|
file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(" << result << ".first);\n";
|
||||||
|
|
||||||
// second return value in pair
|
// second return value in pair
|
||||||
if (isPtr2) {// if we already have a pointer
|
if (isPtr2) {// if we already have a pointer
|
||||||
file.oss << " Shared" << type2 <<"* ret = new Shared" << type2 << "(result.second);" << endl;
|
file.oss << " Shared" << type2 <<"* ret = new Shared" << type2 << "(" << result << ".second);" << endl;
|
||||||
file.oss << " out[1] = wrap_shared_ptr(ret,\"" << matlabType2 << "\");\n";
|
file.oss << " out[1] = wrap_shared_ptr(ret,\"" << matlabType2 << "\");\n";
|
||||||
}
|
}
|
||||||
else if (category2 == ReturnValue::CLASS) { // if we are going to make one
|
else if (category2 == ReturnValue::CLASS) { // if we are going to make one
|
||||||
file.oss << " Shared" << type2 << "* ret = new Shared" << type2 << "(new " << cppType2 << "(result.first));\n";
|
string objCopy;
|
||||||
|
if(typeAttributes.at(cppType1).isVirtual)
|
||||||
|
objCopy = "boost::dynamic_pointer_cast<" + cppType2 + ">(" + result + ".second.clone())";
|
||||||
|
else
|
||||||
|
objCopy = "new " + cppType1 + "(" + result + ".second)";
|
||||||
|
file.oss << " Shared" << type2 << "* ret = new Shared" << type2 << "(" << objCopy << ");\n";
|
||||||
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType2 << "\");\n";
|
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType2 << "\");\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
file.oss << " out[1] = wrap< " << return_type(true,arg2) << " >(result.second);\n";
|
file.oss << " out[1] = wrap< " << return_type(true,arg2) << " >(" << result << ".second);\n";
|
||||||
}
|
}
|
||||||
else if (isPtr1){
|
else if (isPtr1){
|
||||||
file.oss << " Shared" << type1 <<"* ret = new Shared" << type1 << "(result);" << endl;
|
file.oss << " Shared" << type1 <<"* ret = new Shared" << type1 << "(" << result << ");" << endl;
|
||||||
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\");\n";
|
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\");\n";
|
||||||
}
|
}
|
||||||
else if (category1 == ReturnValue::CLASS){
|
else if (category1 == ReturnValue::CLASS){
|
||||||
file.oss << " Shared" << type1 << "* ret = new Shared" << type1 << "(new " << cppType1 << "(result));\n";
|
string objCopy;
|
||||||
|
if(typeAttributes.at(cppType1).isVirtual)
|
||||||
|
objCopy = "boost::dynamic_pointer_cast<" + cppType1 + ">(" + result + ".clone())";
|
||||||
|
else
|
||||||
|
objCopy = "new " + cppType1 + "(" + result + ")";
|
||||||
|
file.oss << " Shared" << type1 << "* ret = new Shared" << type1 << "(" << objCopy << ");\n";
|
||||||
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\");\n";
|
file.oss << " out[0] = wrap_shared_ptr(ret,\"" << matlabType1 << "\");\n";
|
||||||
}
|
}
|
||||||
else if (matlabType1!="void")
|
else if (matlabType1!="void")
|
||||||
file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(result);\n";
|
file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(" << result << ");\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include "FileWriter.h"
|
#include "FileWriter.h"
|
||||||
|
|
||||||
|
@ -17,6 +18,14 @@ namespace wrap {
|
||||||
|
|
||||||
struct ReturnValue {
|
struct ReturnValue {
|
||||||
|
|
||||||
|
struct TypeAttributes {
|
||||||
|
bool isVirtual;
|
||||||
|
TypeAttributes() : isVirtual(false) {}
|
||||||
|
TypeAttributes(bool isVirtual) : isVirtual(isVirtual) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<std::string, TypeAttributes> TypeAttributesTable;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
CLASS,
|
CLASS,
|
||||||
EIGEN,
|
EIGEN,
|
||||||
|
@ -47,7 +56,7 @@ struct ReturnValue {
|
||||||
|
|
||||||
std::string matlab_returnType() const;
|
std::string matlab_returnType() const;
|
||||||
|
|
||||||
void wrap_result(FileWriter& file) const;
|
void wrap_result(const std::string& result, FileWriter& file, const TypeAttributesTable& typeAttributes) const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ void StaticMethod::proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wr
|
||||||
const string& matlabClassName,
|
const string& matlabClassName,
|
||||||
const string& wrapperName,
|
const string& wrapperName,
|
||||||
const vector<string>& using_namespaces,
|
const vector<string>& using_namespaces,
|
||||||
|
const ReturnValue::TypeAttributesTable& typeAttributes,
|
||||||
vector<string>& functionNames) const {
|
vector<string>& functionNames) const {
|
||||||
|
|
||||||
string upperName = name; upperName[0] = std::toupper(upperName[0], std::locale());
|
string upperName = name; upperName[0] = std::toupper(upperName[0], std::locale());
|
||||||
|
@ -82,7 +83,7 @@ void StaticMethod::proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wr
|
||||||
// Output C++ wrapper code
|
// Output C++ wrapper code
|
||||||
|
|
||||||
const string wrapFunctionName = wrapper_fragment(
|
const string wrapFunctionName = wrapper_fragment(
|
||||||
wrapperFile, cppClassName, matlabClassName, overload, id, using_namespaces);
|
wrapperFile, cppClassName, matlabClassName, overload, id, using_namespaces, typeAttributes);
|
||||||
|
|
||||||
// Add to function list
|
// Add to function list
|
||||||
functionNames.push_back(wrapFunctionName);
|
functionNames.push_back(wrapFunctionName);
|
||||||
|
@ -103,7 +104,8 @@ string StaticMethod::wrapper_fragment(FileWriter& file,
|
||||||
const string& matlabClassName,
|
const string& matlabClassName,
|
||||||
int overload,
|
int overload,
|
||||||
int id,
|
int id,
|
||||||
const vector<string>& using_namespaces) const {
|
const vector<string>& using_namespaces,
|
||||||
|
const ReturnValue::TypeAttributesTable& typeAttributes) const {
|
||||||
|
|
||||||
// generate code
|
// generate code
|
||||||
|
|
||||||
|
@ -140,14 +142,11 @@ string StaticMethod::wrapper_fragment(FileWriter& file,
|
||||||
|
|
||||||
file.oss << " ";
|
file.oss << " ";
|
||||||
|
|
||||||
// call method with default type
|
// call method with default type and wrap result
|
||||||
if (returnVal.type1!="void")
|
if (returnVal.type1!="void")
|
||||||
file.oss << returnVal.return_type(true,ReturnValue::pair) << " result = ";
|
returnVal.wrap_result(cppClassName+"::"+name+"("+args.names()+")", file, typeAttributes);
|
||||||
file.oss << cppClassName << "::" << name << "(" << args.names() << ");\n";
|
else
|
||||||
|
file.oss << cppClassName+"::"+name+"("+args.names()+");\n";
|
||||||
// wrap result
|
|
||||||
// example: out[0]=wrap<bool>(result);
|
|
||||||
returnVal.wrap_result(file);
|
|
||||||
|
|
||||||
// finish
|
// finish
|
||||||
file.oss << "}\n";
|
file.oss << "}\n";
|
||||||
|
|
|
@ -50,6 +50,7 @@ struct StaticMethod {
|
||||||
void proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperFile,
|
void proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperFile,
|
||||||
const std::string& cppClassName, const std::string& matlabClassName,
|
const std::string& cppClassName, const std::string& matlabClassName,
|
||||||
const std::string& wrapperName, const std::vector<std::string>& using_namespaces,
|
const std::string& wrapperName, const std::vector<std::string>& using_namespaces,
|
||||||
|
const ReturnValue::TypeAttributesTable& typeAttributes,
|
||||||
std::vector<std::string>& functionNames) const;
|
std::vector<std::string>& functionNames) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -58,7 +59,8 @@ private:
|
||||||
const std::string& matlabClassname,
|
const std::string& matlabClassname,
|
||||||
int overload,
|
int overload,
|
||||||
int id,
|
int id,
|
||||||
const std::vector<std::string>& using_namespaces) const; ///< cpp wrapper
|
const std::vector<std::string>& using_namespaces,
|
||||||
|
const ReturnValue::TypeAttributesTable& typeAttributes) const; ///< cpp wrapper
|
||||||
};
|
};
|
||||||
|
|
||||||
} // \namespace wrap
|
} // \namespace wrap
|
||||||
|
|
|
@ -56,7 +56,7 @@ using namespace boost; // not usual, but for conciseness of generated code
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// "Unique" key to signal calling the matlab object constructor with a raw pointer
|
// "Unique" key to signal calling the matlab object constructor with a raw pointer
|
||||||
// Also present in Class.cpp
|
// Also present in utilities.h
|
||||||
static const uint64_t ptr_constructor_key =
|
static const uint64_t ptr_constructor_key =
|
||||||
(uint64_t('G') << 56) |
|
(uint64_t('G') << 56) |
|
||||||
(uint64_t('T') << 48) |
|
(uint64_t('T') << 48) |
|
||||||
|
@ -119,7 +119,7 @@ void checkArguments(const string& name, int nargout, int nargin, int expected) {
|
||||||
|
|
||||||
// default wrapping throws an error: only basis types are allowed in wrap
|
// default wrapping throws an error: only basis types are allowed in wrap
|
||||||
template <typename Class>
|
template <typename Class>
|
||||||
mxArray* wrap(Class& value) {
|
mxArray* wrap(const Class& value) {
|
||||||
error("wrap internal error: attempted wrap of invalid type");
|
error("wrap internal error: attempted wrap of invalid type");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -127,13 +127,13 @@ mxArray* wrap(Class& value) {
|
||||||
// specialization to string
|
// specialization to string
|
||||||
// wraps into a character array
|
// wraps into a character array
|
||||||
template<>
|
template<>
|
||||||
mxArray* wrap<string>(string& value) {
|
mxArray* wrap<string>(const string& value) {
|
||||||
return mxCreateString(value.c_str());
|
return mxCreateString(value.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// specialization to char
|
// specialization to char
|
||||||
template<>
|
template<>
|
||||||
mxArray* wrap<char>(char& value) {
|
mxArray* wrap<char>(const char& value) {
|
||||||
mxArray *result = scalar(mxUINT32OR64_CLASS);
|
mxArray *result = scalar(mxUINT32OR64_CLASS);
|
||||||
*(char*)mxGetData(result) = value;
|
*(char*)mxGetData(result) = value;
|
||||||
return result;
|
return result;
|
||||||
|
@ -141,7 +141,7 @@ mxArray* wrap<char>(char& value) {
|
||||||
|
|
||||||
// specialization to unsigned char
|
// specialization to unsigned char
|
||||||
template<>
|
template<>
|
||||||
mxArray* wrap<unsigned char>(unsigned char& value) {
|
mxArray* wrap<unsigned char>(const unsigned char& value) {
|
||||||
mxArray *result = scalar(mxUINT32OR64_CLASS);
|
mxArray *result = scalar(mxUINT32OR64_CLASS);
|
||||||
*(unsigned char*)mxGetData(result) = value;
|
*(unsigned char*)mxGetData(result) = value;
|
||||||
return result;
|
return result;
|
||||||
|
@ -149,7 +149,7 @@ mxArray* wrap<unsigned char>(unsigned char& value) {
|
||||||
|
|
||||||
// specialization to bool
|
// specialization to bool
|
||||||
template<>
|
template<>
|
||||||
mxArray* wrap<bool>(bool& value) {
|
mxArray* wrap<bool>(const bool& value) {
|
||||||
mxArray *result = scalar(mxUINT32OR64_CLASS);
|
mxArray *result = scalar(mxUINT32OR64_CLASS);
|
||||||
*(bool*)mxGetData(result) = value;
|
*(bool*)mxGetData(result) = value;
|
||||||
return result;
|
return result;
|
||||||
|
@ -157,7 +157,7 @@ mxArray* wrap<bool>(bool& value) {
|
||||||
|
|
||||||
// specialization to size_t
|
// specialization to size_t
|
||||||
template<>
|
template<>
|
||||||
mxArray* wrap<size_t>(size_t& value) {
|
mxArray* wrap<size_t>(const size_t& value) {
|
||||||
mxArray *result = scalar(mxUINT32OR64_CLASS);
|
mxArray *result = scalar(mxUINT32OR64_CLASS);
|
||||||
*(size_t*)mxGetData(result) = value;
|
*(size_t*)mxGetData(result) = value;
|
||||||
return result;
|
return result;
|
||||||
|
@ -165,7 +165,7 @@ mxArray* wrap<size_t>(size_t& value) {
|
||||||
|
|
||||||
// specialization to int
|
// specialization to int
|
||||||
template<>
|
template<>
|
||||||
mxArray* wrap<int>(int& value) {
|
mxArray* wrap<int>(const int& value) {
|
||||||
mxArray *result = scalar(mxUINT32OR64_CLASS);
|
mxArray *result = scalar(mxUINT32OR64_CLASS);
|
||||||
*(int*)mxGetData(result) = value;
|
*(int*)mxGetData(result) = value;
|
||||||
return result;
|
return result;
|
||||||
|
@ -173,7 +173,7 @@ mxArray* wrap<int>(int& value) {
|
||||||
|
|
||||||
// specialization to double -> just double
|
// specialization to double -> just double
|
||||||
template<>
|
template<>
|
||||||
mxArray* wrap<double>(double& value) {
|
mxArray* wrap<double>(const double& value) {
|
||||||
return mxCreateDoubleScalar(value);
|
return mxCreateDoubleScalar(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,13 +188,7 @@ mxArray* wrap_Vector(const gtsam::Vector& v) {
|
||||||
|
|
||||||
// specialization to Eigen vector -> double vector
|
// specialization to Eigen vector -> double vector
|
||||||
template<>
|
template<>
|
||||||
mxArray* wrap<gtsam::Vector >(gtsam::Vector& v) {
|
mxArray* wrap<gtsam::Vector >(const gtsam::Vector& v) {
|
||||||
return wrap_Vector(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
// const version
|
|
||||||
template<>
|
|
||||||
mxArray* wrap<const gtsam::Vector >(const gtsam::Vector& v) {
|
|
||||||
return wrap_Vector(v);
|
return wrap_Vector(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,13 +208,7 @@ mxArray* wrap_Matrix(const gtsam::Matrix& A) {
|
||||||
|
|
||||||
// specialization to Eigen MATRIX -> double matrix
|
// specialization to Eigen MATRIX -> double matrix
|
||||||
template<>
|
template<>
|
||||||
mxArray* wrap<gtsam::Matrix >(gtsam::Matrix& A) {
|
mxArray* wrap<gtsam::Matrix >(const gtsam::Matrix& A) {
|
||||||
return wrap_Matrix(A);
|
|
||||||
}
|
|
||||||
|
|
||||||
// const version
|
|
||||||
template<>
|
|
||||||
mxArray* wrap<const gtsam::Matrix >(const gtsam::Matrix& A) {
|
|
||||||
return wrap_Matrix(A);
|
return wrap_Matrix(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,9 +330,14 @@ gtsam::Matrix unwrap< gtsam::Matrix >(const mxArray* array) {
|
||||||
[create_object] creates a MATLAB proxy class object with a mexhandle
|
[create_object] creates a MATLAB proxy class object with a mexhandle
|
||||||
in the self property. Matlab does not allow the creation of matlab
|
in the self property. Matlab does not allow the creation of matlab
|
||||||
objects from within mex files, hence we resort to an ugly trick: we
|
objects from within mex files, hence we resort to an ugly trick: we
|
||||||
invoke the proxy class constructor by calling MATLAB, and pass 13
|
invoke the proxy class constructor by calling MATLAB with a special
|
||||||
dummy arguments to let the constructor know we want an object without
|
uint64 value ptr_constructor_key and the pointer itself. MATLAB
|
||||||
the self property initialized. We then assign the mexhandle to self.
|
allocates the object. Then, the special constructor in our wrap code
|
||||||
|
that is activated when the ptr_constructor_key is passed in passes
|
||||||
|
the pointer back into a C++ function to add the pointer to its
|
||||||
|
collector. We go through this extra "C++ to MATLAB to C++ step" in
|
||||||
|
order to be able to add to the collector could be in a different wrap
|
||||||
|
module.
|
||||||
*/
|
*/
|
||||||
mxArray* create_object(const char *classname, void *pointer) {
|
mxArray* create_object(const char *classname, void *pointer) {
|
||||||
mxArray *result;
|
mxArray *result;
|
||||||
|
@ -376,9 +369,9 @@ mxArray* wrap_shared_ptr(boost::shared_ptr< Class >* shared_ptr, const char *cla
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Class>
|
template <typename Class>
|
||||||
boost::shared_ptr<Class> unwrap_shared_ptr(const mxArray* obj, const string& className) {
|
boost::shared_ptr<Class> unwrap_shared_ptr(const mxArray* obj, const string& propertyName) {
|
||||||
|
|
||||||
mxArray* mxh = mxGetProperty(obj,0,"self");
|
mxArray* mxh = mxGetProperty(obj,0, propertyName.c_str());
|
||||||
if (mxGetClassID(mxh) != mxUINT32OR64_CLASS || mxIsComplex(mxh)
|
if (mxGetClassID(mxh) != mxUINT32OR64_CLASS || mxIsComplex(mxh)
|
||||||
|| mxGetM(mxh) != 1 || mxGetN(mxh) != 1) error(
|
|| mxGetM(mxh) != 1 || mxGetN(mxh) != 1) error(
|
||||||
"Parameter is not an Shared type.");
|
"Parameter is not an Shared type.");
|
||||||
|
|
|
@ -135,6 +135,21 @@ void generateIncludes(FileWriter& file, const string& class_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
|
string qualifiedName(const string& separator, const vector<string>& names, const string& finalName) {
|
||||||
|
string result;
|
||||||
|
if(!names.empty()) {
|
||||||
|
for(size_t i = 0; i < names.size() - 1; ++i)
|
||||||
|
result += (names[i] + separator);
|
||||||
|
if(finalName.empty())
|
||||||
|
result += names.back();
|
||||||
|
else
|
||||||
|
result += (names.back() + separator + finalName);
|
||||||
|
} else if(!finalName.empty()) {
|
||||||
|
result = finalName;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
||||||
} // \namespace wrap
|
} // \namespace wrap
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
#include "FileWriter.h"
|
#include "FileWriter.h"
|
||||||
|
|
||||||
|
@ -28,44 +31,54 @@ namespace wrap {
|
||||||
|
|
||||||
class CantOpenFile : public std::exception {
|
class CantOpenFile : public std::exception {
|
||||||
private:
|
private:
|
||||||
std::string filename_;
|
const std::string what_;
|
||||||
public:
|
public:
|
||||||
CantOpenFile(const std::string& filename) : filename_(filename) {}
|
CantOpenFile(const std::string& filename) : what_("Can't open file " + filename) {}
|
||||||
~CantOpenFile() throw() {}
|
~CantOpenFile() throw() {}
|
||||||
virtual const char* what() const throw() {
|
virtual const char* what() const throw() { return what_.c_str(); }
|
||||||
return ("Can't open file " + filename_).c_str();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ParseFailed : public std::exception {
|
class ParseFailed : public std::exception {
|
||||||
private:
|
private:
|
||||||
int length_;
|
const std::string what_;
|
||||||
public:
|
public:
|
||||||
ParseFailed(int length) : length_(length) {}
|
ParseFailed(int length) : what_((boost::format("Parse failed at character [%d]")%(length-1)).str()) {}
|
||||||
~ParseFailed() throw() {}
|
~ParseFailed() throw() {}
|
||||||
virtual const char* what() const throw() {
|
virtual const char* what() const throw() { return what_.c_str(); }
|
||||||
std::stringstream buf;
|
|
||||||
int len = length_+1;
|
|
||||||
buf << "Parse failed at character [" << len << "]";
|
|
||||||
return buf.str().c_str();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class DependencyMissing : public std::exception {
|
class DependencyMissing : public std::exception {
|
||||||
private:
|
private:
|
||||||
std::string dependency_;
|
const std::string what_;
|
||||||
std::string location_;
|
|
||||||
public:
|
public:
|
||||||
DependencyMissing(const std::string& dep, const std::string& loc) {
|
DependencyMissing(const std::string& dep, const std::string& loc) :
|
||||||
dependency_ = dep;
|
what_("Missing dependency " + dep + " in " + loc) {}
|
||||||
location_ = loc;
|
|
||||||
}
|
|
||||||
~DependencyMissing() throw() {}
|
~DependencyMissing() throw() {}
|
||||||
virtual const char* what() const throw() {
|
virtual const char* what() const throw() { return what_.c_str(); }
|
||||||
return ("Missing dependency " + dependency_ + " in " + location_).c_str();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DuplicateDefinition : public std::exception {
|
||||||
|
private:
|
||||||
|
const std::string what_;
|
||||||
|
public:
|
||||||
|
DuplicateDefinition(const std::string& name) :
|
||||||
|
what_("Duplicate definition of " + name) {}
|
||||||
|
~DuplicateDefinition() throw() {}
|
||||||
|
virtual const char* what() const throw() { return what_.c_str(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Special "magic number" passed into MATLAB constructor to indicate creating
|
||||||
|
* a MATLAB object from a shared_ptr allocated in C++
|
||||||
|
*/
|
||||||
|
static const uint64_t ptr_constructor_key =
|
||||||
|
(uint64_t('G') << 56) |
|
||||||
|
(uint64_t('T') << 48) |
|
||||||
|
(uint64_t('S') << 40) |
|
||||||
|
(uint64_t('A') << 32) |
|
||||||
|
(uint64_t('M') << 24) |
|
||||||
|
(uint64_t('p') << 16) |
|
||||||
|
(uint64_t('t') << 8) |
|
||||||
|
(uint64_t('r'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read contents of a file into a std::string
|
* read contents of a file into a std::string
|
||||||
|
@ -98,4 +111,10 @@ void generateUsingNamespace(FileWriter& file, const std::vector<std::string>& us
|
||||||
void generateIncludes(FileWriter& file, const std::string& class_name,
|
void generateIncludes(FileWriter& file, const std::string& class_name,
|
||||||
const std::vector<std::string>& includes);
|
const std::vector<std::string>& includes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a qualified name, if finalName is empty, only the names vector will
|
||||||
|
* be used (i.e. there won't be a trailing separator on the qualified name).
|
||||||
|
*/
|
||||||
|
std::string qualifiedName(const std::string& separator, const std::vector<std::string>& names, const std::string& finalName = "");
|
||||||
|
|
||||||
} // \namespace wrap
|
} // \namespace wrap
|
||||||
|
|
Loading…
Reference in New Issue