diff --git a/.cproject b/.cproject
index 9c03c5b7d..241afea81 100644
--- a/.cproject
+++ b/.cproject
@@ -2393,6 +2393,38 @@
true
true
+
+ make
+ -j4
+ testType.run
+ true
+ true
+ true
+
+
+ make
+ -j4
+ testArgument.run
+ true
+ true
+ true
+
+
+ make
+ -j4
+ testReturnValue.run
+ true
+ true
+ true
+
+
+ make
+ -j4
+ testTemplate.run
+ true
+ true
+ true
+
make
-j5
diff --git a/gtsam.h b/gtsam.h
index d63563028..96d51117a 100644
--- a/gtsam.h
+++ b/gtsam.h
@@ -1738,6 +1738,8 @@ class Values {
void insert(size_t j, const gtsam::Cal3Bundler& t);
void insert(size_t j, const gtsam::EssentialMatrix& t);
void insert(size_t j, const gtsam::imuBias::ConstantBias& t);
+ void insert(size_t j, Vector t);
+ void insert(size_t j, Matrix t);
void update(size_t j, const gtsam::Point2& t);
void update(size_t j, const gtsam::Point3& t);
@@ -1750,9 +1752,10 @@ class Values {
void update(size_t j, const gtsam::Cal3Bundler& t);
void update(size_t j, const gtsam::EssentialMatrix& t);
void update(size_t j, const gtsam::imuBias::ConstantBias& t);
+ void update(size_t j, Vector t);
+ void update(size_t j, Matrix t);
- template
+ template
T at(size_t j);
};
@@ -2150,7 +2153,7 @@ class NonlinearISAM {
#include
#include
-template
+template
virtual class PriorFactor : gtsam::NoiseModelFactor {
PriorFactor(size_t key, const T& prior, const gtsam::noiseModel::Base* noiseModel);
T prior() const;
diff --git a/gtsam/base/Manifold.h b/gtsam/base/Manifold.h
index a3a5b029b..1190822ed 100644
--- a/gtsam/base/Manifold.h
+++ b/gtsam/base/Manifold.h
@@ -73,7 +73,6 @@ template
struct dimension: public Dynamic {
};
-
/**
* zero::value is intended to be the origin of a canonical coordinate system
* with canonical(t) == DefaultChart::local(zero::value, t)
@@ -111,14 +110,16 @@ struct is_group > : publi
};
template
-struct is_manifold > : public boost::true_type{
+struct is_manifold > : public boost::true_type {
};
template
-struct dimension > : public boost::integral_constant {
- //TODO after switch to c++11 : the above should should be extracted to a constexpr function
- // for readability and to reduce code duplication
+struct dimension > : public boost::integral_constant<
+ int,
+ M == Eigen::Dynamic ? Eigen::Dynamic :
+ (N == Eigen::Dynamic ? Eigen::Dynamic : M * N)> {
+ //TODO after switch to c++11 : the above should should be extracted to a constexpr function
+ // for readability and to reduce code duplication
};
template
@@ -131,10 +132,10 @@ struct zero > {
};
template
-struct identity > : public zero > {
+struct identity > : public zero<
+ Eigen::Matrix > {
};
-
template struct is_chart: public boost::false_type {
};
@@ -248,12 +249,16 @@ struct DefaultChart > {
* This chart for the vector space of M x N matrices (represented by Eigen matrices) chooses as basis the one with respect to which the coordinates are exactly the matrix entries as laid out in memory (as determined by Options).
* Computing coordinates for a matrix is then simply a reshape to the row vector of appropriate size.
*/
- typedef Eigen::Matrix type;
+ typedef Eigen::Matrix type;
typedef type T;
- typedef Eigen::Matrix::value, 1> vector;BOOST_STATIC_ASSERT_MSG((M!=Eigen::Dynamic && N!=Eigen::Dynamic),
- "DefaultChart has not been implemented yet for dynamically sized matrices");
+ typedef Eigen::Matrix::value, 1> vector;
+
+ BOOST_STATIC_ASSERT_MSG((M!=Eigen::Dynamic && N!=Eigen::Dynamic),
+ "Internal error: DefaultChart for Dynamic should be handled by template below");
+
static vector local(const T& origin, const T& other) {
- return reshape(other) - reshape(origin);
+ return reshape(other)
+ - reshape(origin);
}
static T retract(const T& origin, const vector& d) {
return origin + reshape(d);
@@ -266,20 +271,36 @@ struct DefaultChart > {
// Dynamically sized Vector
template<>
struct DefaultChart {
- typedef Vector T;
- typedef T type;
- typedef T vector;
- static vector local(const T& origin, const T& other) {
+ typedef Vector type;
+ typedef Vector vector;
+ static vector local(const Vector& origin, const Vector& other) {
return other - origin;
}
- static T retract(const T& origin, const vector& d) {
+ static Vector retract(const Vector& origin, const vector& d) {
return origin + d;
}
- static int getDimension(const T& origin) {
+ static int getDimension(const Vector& origin) {
return origin.size();
}
};
+// Dynamically sized Matrix
+template<>
+struct DefaultChart {
+ typedef Matrix type;
+ typedef Vector vector;
+ static vector local(const Matrix& origin, const Matrix& other) {
+ Matrix d = other - origin;
+ return Eigen::Map(d.data(),getDimension(d));
+ }
+ static Matrix retract(const Matrix& origin, const vector& d) {
+ return origin + Eigen::Map(d.data(),origin.rows(),origin.cols());
+ }
+ static int getDimension(const Matrix& m) {
+ return m.size();
+ }
+};
+
/**
* Old Concept check class for Manifold types
* Requires a mapping between a linear tangent space and the underlying
diff --git a/gtsam/nonlinear/tests/testValues.cpp b/gtsam/nonlinear/tests/testValues.cpp
index 09fe0f253..941728d8c 100644
--- a/gtsam/nonlinear/tests/testValues.cpp
+++ b/gtsam/nonlinear/tests/testValues.cpp
@@ -12,6 +12,8 @@
/**
* @file testValues.cpp
* @author Richard Roberts
+ * @author Frank Dellaert
+ * @author Mike Bosse
*/
#include
@@ -168,9 +170,9 @@ TEST(Values, basic_functions)
Values values;
const Values& values_c = values;
values.insert(2, Vector3());
- values.insert(4, Vector3());
- values.insert(6, Vector3());
- values.insert(8, Vector3());
+ values.insert(4, Vector(3));
+ values.insert(6, Matrix23());
+ values.insert(8, Matrix(2,3));
// find
EXPECT_LONGS_EQUAL(4, values.find(4)->key);
diff --git a/matlab/gtsam_tests/.gitignore b/matlab/gtsam_tests/.gitignore
new file mode 100644
index 000000000..6d725d9bc
--- /dev/null
+++ b/matlab/gtsam_tests/.gitignore
@@ -0,0 +1 @@
+*.m~
diff --git a/matlab/gtsam_tests/testValues.m b/matlab/gtsam_tests/testValues.m
new file mode 100644
index 000000000..fe2cd30fe
--- /dev/null
+++ b/matlab/gtsam_tests/testValues.m
@@ -0,0 +1,40 @@
+% test wrapping of Values
+import gtsam.*;
+
+values = Values;
+E = EssentialMatrix(Rot3,Unit3);
+tol = 1e-9;
+
+values.insert(0, Point2);
+values.insert(1, Point3);
+values.insert(2, Rot2);
+values.insert(3, Pose2);
+values.insert(4, Rot3);
+values.insert(5, Pose3);
+values.insert(6, Cal3_S2);
+values.insert(7, Cal3DS2);
+values.insert(8, Cal3Bundler);
+values.insert(9, E);
+values.insert(10, imuBias.ConstantBias);
+
+% special cases for Vector and Matrix:
+values.insert(11, [1;2;3]);
+values.insert(12, [1 2;3 4]);
+
+EXPECT('at',values.atPoint2(0).equals(Point2,tol));
+EXPECT('at',values.atPoint3(1).equals(Point3,tol));
+EXPECT('at',values.atRot2(2).equals(Rot2,tol));
+EXPECT('at',values.atPose2(3).equals(Pose2,tol));
+EXPECT('at',values.atRot3(4).equals(Rot3,tol));
+EXPECT('at',values.atPose3(5).equals(Pose3,tol));
+EXPECT('at',values.atCal3_S2(6).equals(Cal3_S2,tol));
+EXPECT('at',values.atCal3DS2(7).equals(Cal3DS2,tol));
+EXPECT('at',values.atCal3Bundler(8).equals(Cal3Bundler,tol));
+EXPECT('at',values.atEssentialMatrix(9).equals(E,tol));
+EXPECT('at',values.atConstantBias(10).equals(imuBias.ConstantBias,tol));
+
+% special cases for Vector and Matrix:
+actualVector = values.atVector(11);
+EQUALITY('at',[1;2;3],actualVector,tol);
+actualMatrix = values.atMatrix(12);
+EQUALITY('at',[1 2;3 4],actualMatrix,tol);
diff --git a/matlab/gtsam_tests/test_gtsam.m b/matlab/gtsam_tests/test_gtsam.m
index e3705948d..e08019610 100644
--- a/matlab/gtsam_tests/test_gtsam.m
+++ b/matlab/gtsam_tests/test_gtsam.m
@@ -1,5 +1,8 @@
% Test runner script - runs each test
+display 'Starting: testValues'
+testValues
+
display 'Starting: testJacobianFactor'
testJacobianFactor
diff --git a/wrap/Argument.cpp b/wrap/Argument.cpp
index 4989afb0d..1f57917d8 100644
--- a/wrap/Argument.cpp
+++ b/wrap/Argument.cpp
@@ -20,6 +20,7 @@
#include
#include
+#include
#include
#include
@@ -31,12 +32,13 @@ using namespace wrap;
/* ************************************************************************* */
Argument Argument::expandTemplate(const TemplateSubstitution& ts) const {
Argument instArg = *this;
- instArg.type = ts(type);
+ instArg.type = ts.tryToSubstitite(type);
return instArg;
}
/* ************************************************************************* */
-ArgumentList ArgumentList::expandTemplate(const TemplateSubstitution& ts) const {
+ArgumentList ArgumentList::expandTemplate(
+ const TemplateSubstitution& ts) const {
ArgumentList instArgList;
BOOST_FOREACH(const Argument& arg, *this) {
Argument instArg = arg.expandTemplate(ts);
@@ -48,25 +50,25 @@ ArgumentList ArgumentList::expandTemplate(const TemplateSubstitution& ts) const
/* ************************************************************************* */
string Argument::matlabClass(const string& delim) const {
string result;
- BOOST_FOREACH(const string& ns, type.namespaces)
+ BOOST_FOREACH(const string& ns, type.namespaces())
result += ns + delim;
- if (type.name == "string" || type.name == "unsigned char"
- || type.name == "char")
+ if (type.name() == "string" || type.name() == "unsigned char"
+ || type.name() == "char")
return result + "char";
- if (type.name == "Vector" || type.name == "Matrix")
+ if (type.name() == "Vector" || type.name() == "Matrix")
return result + "double";
- if (type.name == "int" || type.name == "size_t")
+ if (type.name() == "int" || type.name() == "size_t")
return result + "numeric";
- if (type.name == "bool")
+ if (type.name() == "bool")
return result + "logical";
- return result + type.name;
+ return result + type.name();
}
/* ************************************************************************* */
bool Argument::isScalar() const {
- return (type.name == "bool" || type.name == "char"
- || type.name == "unsigned char" || type.name == "int"
- || type.name == "size_t" || type.name == "double");
+ return (type.name() == "bool" || type.name() == "char"
+ || type.name() == "unsigned char" || type.name() == "int"
+ || type.name() == "size_t" || type.name() == "double");
}
/* ************************************************************************* */
@@ -97,6 +99,13 @@ void Argument::matlab_unwrap(FileWriter& file, const string& matlabName) const {
file.oss << ");" << endl;
}
+/* ************************************************************************* */
+void Argument::proxy_check(FileWriter& proxyFile, const string& s) const {
+ proxyFile.oss << "isa(" << s << ",'" << matlabClass(".") << "')";
+ if (type.name() == "Vector")
+ proxyFile.oss << " && size(" << s << ",2)==1";
+}
+
/* ************************************************************************* */
string ArgumentList::types() const {
string str;
@@ -104,7 +113,7 @@ string ArgumentList::types() const {
BOOST_FOREACH(Argument arg, *this) {
if (!first)
str += ",";
- str += arg.type.name;
+ str += arg.type.name();
first = false;
}
return str;
@@ -116,14 +125,14 @@ string ArgumentList::signature() const {
bool cap = false;
BOOST_FOREACH(Argument arg, *this) {
- BOOST_FOREACH(char ch, arg.type.name)
+ BOOST_FOREACH(char ch, arg.type.name())
if (isupper(ch)) {
sig += ch;
//If there is a capital letter, we don't want to read it below
cap = true;
}
if (!cap)
- sig += arg.type.name[0];
+ sig += arg.type.name()[0];
//Reset to default
cap = false;
}
@@ -170,25 +179,14 @@ void ArgumentList::emit_prototype(FileWriter& file, const string& name) const {
BOOST_FOREACH(Argument arg, *this) {
if (!first)
file.oss << ", ";
- file.oss << arg.type.name << " " << arg.name;
+ file.oss << arg.type.name() << " " << arg.name;
first = false;
}
file.oss << ")";
}
+
/* ************************************************************************* */
-void ArgumentList::emit_call(FileWriter& proxyFile,
- const ReturnValue& returnVal, const string& wrapperName, int id,
- bool staticMethod) const {
- returnVal.emit_matlab(proxyFile);
- proxyFile.oss << wrapperName << "(" << id;
- if (!staticMethod)
- proxyFile.oss << ", this";
- proxyFile.oss << ", varargin{:});\n";
-}
-/* ************************************************************************* */
-void ArgumentList::emit_conditional_call(FileWriter& proxyFile,
- const ReturnValue& returnVal, const string& wrapperName, int id,
- bool staticMethod) const {
+void ArgumentList::proxy_check(FileWriter& proxyFile) const {
// Check nr of arguments
proxyFile.oss << "if length(varargin) == " << size();
if (size() > 0)
@@ -198,15 +196,12 @@ void ArgumentList::emit_conditional_call(FileWriter& proxyFile,
for (size_t i = 0; i < size(); i++) {
if (!first)
proxyFile.oss << " && ";
- proxyFile.oss << "isa(varargin{" << i + 1 << "},'"
- << (*this)[i].matlabClass(".") << "')";
+ string s = "varargin{" + boost::lexical_cast(i + 1) + "}";
+ (*this)[i].proxy_check(proxyFile, s);
first = false;
}
proxyFile.oss << "\n";
-
- // output call to C++ wrapper
- proxyFile.oss << " ";
- emit_call(proxyFile, returnVal, wrapperName, id, staticMethod);
}
+
/* ************************************************************************* */
diff --git a/wrap/Argument.h b/wrap/Argument.h
index 3d8d7288f..3b7a13ee3 100644
--- a/wrap/Argument.h
+++ b/wrap/Argument.h
@@ -28,13 +28,23 @@ namespace wrap {
/// Argument class
struct Argument {
Qualified type;
- bool is_const, is_ref, is_ptr;
std::string name;
+ bool is_const, is_ref, is_ptr;
Argument() :
is_const(false), is_ref(false), is_ptr(false) {
}
+ Argument(const Qualified& t, const std::string& n) :
+ type(t), name(n), is_const(false), is_ref(false), is_ptr(false) {
+ }
+
+ bool operator==(const Argument& other) const {
+ return type == other.type && name == other.name
+ && is_const == other.is_const && is_ref == other.is_ref
+ && is_ptr == other.is_ptr;
+ }
+
Argument expandTemplate(const TemplateSubstitution& ts) const;
/// return MATLAB class for use in isa(x,class)
@@ -46,6 +56,12 @@ struct Argument {
/// MATLAB code generation, MATLAB to C++
void matlab_unwrap(FileWriter& file, const std::string& matlabName) const;
+ /**
+ * emit checking argument to MATLAB proxy
+ * @param proxyFile output stream
+ */
+ void proxy_check(FileWriter& proxyFile, const std::string& s) const;
+
friend std::ostream& operator<<(std::ostream& os, const Argument& arg) {
os << (arg.is_const ? "const " : "") << arg.type << (arg.is_ptr ? "*" : "")
<< (arg.is_ref ? "&" : "");
@@ -88,26 +104,12 @@ struct ArgumentList: public std::vector {
void emit_prototype(FileWriter& file, const std::string& name) const;
/**
- * emit emit MATLAB call to proxy
+ * emit checking arguments to MATLAB proxy
* @param proxyFile output stream
- * @param returnVal the return value
- * @param wrapperName of method or function
- * @param staticMethod flag to emit "this" in call
*/
- void emit_call(FileWriter& proxyFile, const ReturnValue& returnVal,
- const std::string& wrapperName, int id, bool staticMethod = false) const;
-
- /**
- * emit conditional MATLAB call to proxy (checking arguments first)
- * @param proxyFile output stream
- * @param returnVal the return value
- * @param wrapperName of method or function
- * @param staticMethod flag to emit "this" in call
- */
- void emit_conditional_call(FileWriter& proxyFile,
- const ReturnValue& returnVal, const std::string& wrapperName, int id,
- bool staticMethod = false) const;
+ void proxy_check(FileWriter& proxyFile) const;
+ /// Output stream operator
friend std::ostream& operator<<(std::ostream& os,
const ArgumentList& argList) {
os << "(";
@@ -122,5 +124,87 @@ struct ArgumentList: public std::vector {
};
-} // \namespace wrap
+/* ************************************************************************* */
+// http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html
+struct ArgumentGrammar: public classic::grammar {
+
+ wrap::Argument& result_; ///< successful parse will be placed in here
+ TypeGrammar argument_type_g; ///< Type parser for Argument::type
+
+ /// Construct type grammar and specify where result is placed
+ ArgumentGrammar(wrap::Argument& result) :
+ result_(result), argument_type_g(result.type) {
+ }
+
+ /// Definition of type grammar
+ template
+ struct definition: BasicRules {
+
+ typedef classic::rule Rule;
+
+ Rule argument_p;
+
+ definition(ArgumentGrammar const& self) {
+ using namespace classic;
+
+ // NOTE: allows for pointers to all types
+ // Slightly more permissive than before on basis/eigen type qualification
+ // Also, currently parses Point2*&, can't make it work otherwise :-(
+ argument_p = !str_p("const")[assign_a(self.result_.is_const, T)] //
+ >> self.argument_type_g //
+ >> !ch_p('*')[assign_a(self.result_.is_ptr, T)]
+ >> !ch_p('&')[assign_a(self.result_.is_ref, T)]
+ >> BasicRules::name_p[assign_a(self.result_.name)];
+ }
+
+ Rule const& start() const {
+ return argument_p;
+ }
+
+ };
+};
+// ArgumentGrammar
+
+/* ************************************************************************* */
+// http://boost-spirit.com/distrib/spirit_1_8_2/libs/spirit/doc/grammar.html
+struct ArgumentListGrammar: public classic::grammar {
+
+ wrap::ArgumentList& result_; ///< successful parse will be placed in here
+
+ const Argument arg0; ///< used to reset arg
+ mutable Argument arg; ///< temporary argument for use during parsing
+ ArgumentGrammar argument_g; ///< single Argument parser
+
+ /// Construct type grammar and specify where result is placed
+ ArgumentListGrammar(wrap::ArgumentList& result) :
+ result_(result), argument_g(arg) {
+ }
+
+ /// Definition of type grammar
+ template
+ struct definition {
+
+ classic::rule argument_p, argumentList_p;
+
+ definition(ArgumentListGrammar const& self) {
+ using namespace classic;
+
+ argument_p = self.argument_g //
+ [classic::push_back_a(self.result_, self.arg)] //
+ [assign_a(self.arg, self.arg0)];
+
+ argumentList_p = '(' >> !argument_p >> *(',' >> argument_p) >> ')';
+ }
+
+ classic::rule const& start() const {
+ return argumentList_p;
+ }
+
+ };
+};
+// ArgumentListGrammar
+
+/* ************************************************************************* */
+
+}// \namespace wrap
diff --git a/wrap/Class.cpp b/wrap/Class.cpp
index 0e480f0fd..6e415065d 100644
--- a/wrap/Class.cpp
+++ b/wrap/Class.cpp
@@ -22,23 +22,68 @@
#include
#include
+#include
+#include
#include
#include
#include
+#include // std::ostream_iterator
//#include // on Linux GCC: fails with error regarding needing C++0x std flags
//#include // same failure as above
#include // works on Linux GCC
using namespace std;
using namespace wrap;
+/* ************************************************************************* */
+void Class::assignParent(const Qualified& parent) {
+ parentClass.reset(parent);
+}
+
+/* ************************************************************************* */
+boost::optional Class::qualifiedParent() const {
+ boost::optional result = boost::none;
+ if (parentClass)
+ result = parentClass->qualifiedName("::");
+ return result;
+}
+
+/* ************************************************************************* */
+static void handleException(const out_of_range& oor,
+ const Class::Methods& methods) {
+ cerr << "Class::method: key not found: " << oor.what() << ", methods are:\n";
+ using boost::adaptors::map_keys;
+ ostream_iterator out_it(cerr, "\n");
+ boost::copy(methods | map_keys, out_it);
+}
+
+/* ************************************************************************* */
+Method& Class::mutableMethod(Str key) {
+ try {
+ return methods_.at(key);
+ } catch (const out_of_range& oor) {
+ handleException(oor, methods_);
+ throw runtime_error("Internal error in wrap");
+ }
+}
+
+/* ************************************************************************* */
+const Method& Class::method(Str key) const {
+ try {
+ return methods_.at(key);
+ } catch (const out_of_range& oor) {
+ handleException(oor, methods_);
+ throw runtime_error("Internal error in wrap");
+ }
+}
+
/* ************************************************************************* */
void Class::matlab_proxy(Str toolboxPath, Str wrapperName,
const TypeAttributesTable& typeAttributes, FileWriter& wrapperFile,
vector& functionNames) const {
// Create namespace folders
- createNamespaceStructure(namespaces, toolboxPath);
+ createNamespaceStructure(namespaces(), toolboxPath);
// open destination classFile
string classFile = matlabName(toolboxPath);
@@ -48,21 +93,20 @@ void Class::matlab_proxy(Str toolboxPath, Str wrapperName,
const string matlabQualName = qualifiedName(".");
const string matlabUniqueName = qualifiedName();
const string cppName = qualifiedName("::");
- const string matlabBaseName = qualifiedParent.qualifiedName(".");
- const string cppBaseName = qualifiedParent.qualifiedName("::");
// emit class proxy code
// we want our class to inherit the handle class for memory purposes
- const string parent = qualifiedParent.empty() ? "handle" : matlabBaseName;
+ const string parent =
+ parentClass ? parentClass->qualifiedName(".") : "handle";
comment_fragment(proxyFile);
- proxyFile.oss << "classdef " << name << " < " << parent << endl;
+ proxyFile.oss << "classdef " << name() << " < " << parent << endl;
proxyFile.oss << " properties\n";
proxyFile.oss << " ptr_" << matlabUniqueName << " = 0\n";
proxyFile.oss << " end\n";
proxyFile.oss << " methods\n";
// Constructor
- proxyFile.oss << " function obj = " << name << "(varargin)\n";
+ proxyFile.oss << " function obj = " << name() << "(varargin)\n";
// 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
@@ -75,11 +119,12 @@ void Class::matlab_proxy(Str toolboxPath, Str wrapperName,
wrapperFile.oss << "\n";
// Regular constructors
+ boost::optional cppBaseName = qualifiedParent();
for (size_t i = 0; i < constructor.nrOverloads(); i++) {
ArgumentList args = constructor.argumentList(i);
const int id = (int) functionNames.size();
- constructor.proxy_fragment(proxyFile, wrapperName, !qualifiedParent.empty(),
- id, args);
+ constructor.proxy_fragment(proxyFile, wrapperName, (bool) parentClass, id,
+ args);
const string wrapFunctionName = constructor.wrapper_fragment(wrapperFile,
cppName, matlabUniqueName, cppBaseName, id, args);
wrapperFile.oss << "\n";
@@ -89,9 +134,9 @@ void Class::matlab_proxy(Str toolboxPath, Str wrapperName,
proxyFile.oss << " error('Arguments do not match any overload of "
<< matlabQualName << " constructor');\n";
proxyFile.oss << " end\n";
- if (!qualifiedParent.empty())
- proxyFile.oss << " obj = obj@" << matlabBaseName << "(uint64("
- << ptr_constructor_key << "), base_ptr);\n";
+ if (parentClass)
+ proxyFile.oss << " obj = obj@" << parentClass->qualifiedName(".")
+ << "(uint64(" << ptr_constructor_key << "), base_ptr);\n";
proxyFile.oss << " obj.ptr_" << matlabUniqueName << " = my_ptr;\n";
proxyFile.oss << " end\n\n";
@@ -111,7 +156,7 @@ void Class::matlab_proxy(Str toolboxPath, Str wrapperName,
<< " function disp(obj), obj.display; end\n %DISP Calls print on the object\n";
// Methods
- BOOST_FOREACH(const Methods::value_type& name_m, methods) {
+ BOOST_FOREACH(const Methods::value_type& name_m, methods_) {
const Method& m = name_m.second;
m.proxy_wrapper_fragments(proxyFile, wrapperFile, cppName, matlabQualName,
matlabUniqueName, wrapperName, typeAttributes, functionNames);
@@ -151,7 +196,6 @@ void Class::pointer_constructor_fragments(FileWriter& proxyFile,
const string matlabUniqueName = qualifiedName();
const string cppName = qualifiedName("::");
- const string baseCppName = qualifiedParent.qualifiedName("::");
const int collectorInsertId = (int) functionNames.size();
const string collectorInsertFunctionName = matlabUniqueName
@@ -188,7 +232,7 @@ void Class::pointer_constructor_fragments(FileWriter& proxyFile,
} else {
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
+ if (!parentClass) // If this class has a base class, we'll get a base class pointer back
proxyFile.oss << " ";
else
proxyFile.oss << " base_ptr = ";
@@ -211,9 +255,10 @@ void Class::pointer_constructor_fragments(FileWriter& proxyFile,
// Add to collector
wrapperFile.oss << " collector_" << matlabUniqueName << ".insert(self);\n";
// 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()) {
+ boost::optional cppBaseName = qualifiedParent();
+ if (cppBaseName) {
wrapperFile.oss << "\n";
- wrapperFile.oss << " typedef boost::shared_ptr<" << baseCppName
+ wrapperFile.oss << " typedef boost::shared_ptr<" << *cppBaseName
<< "> SharedBase;\n";
wrapperFile.oss
<< " out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);\n";
@@ -244,10 +289,10 @@ void Class::pointer_constructor_fragments(FileWriter& proxyFile,
/* ************************************************************************* */
Class Class::expandTemplate(const TemplateSubstitution& ts) const {
Class inst = *this;
- inst.methods = expandMethodTemplate(methods, ts);
+ inst.methods_ = expandMethodTemplate(methods_, ts);
inst.static_methods = expandMethodTemplate(static_methods, ts);
inst.constructor = constructor.expandTemplate(ts);
- inst.deconstructor.name = inst.name;
+ inst.deconstructor.name = inst.name();
return inst;
}
@@ -257,10 +302,10 @@ vector Class::expandTemplate(Str templateArg,
vector result;
BOOST_FOREACH(const Qualified& instName, instantiations) {
Qualified expandedClass = (Qualified) (*this);
- expandedClass.name += instName.name;
+ expandedClass.expand(instName.name());
const TemplateSubstitution ts(templateArg, instName, expandedClass);
Class inst = expandTemplate(ts);
- inst.name = expandedClass.name;
+ inst.name_ = expandedClass.name();
inst.templateArgs.clear();
inst.typedefName = qualifiedName("::") + "<" + instName.qualifiedName("::")
+ ">";
@@ -272,50 +317,50 @@ vector Class::expandTemplate(Str templateArg,
/* ************************************************************************* */
void Class::addMethod(bool verbose, bool is_const, Str methodName,
const ArgumentList& argumentList, const ReturnValue& returnValue,
- Str templateArgName, const vector& templateArgValues) {
+ const Template& tmplate) {
// Check if templated
- if (!templateArgName.empty() && templateArgValues.size() > 0) {
+ if (tmplate.valid()) {
// Create method to expand
// For all values of the template argument, create a new method
- BOOST_FOREACH(const Qualified& instName, templateArgValues) {
- const TemplateSubstitution ts(templateArgName, instName, this->name);
+ BOOST_FOREACH(const Qualified& instName, tmplate.argValues()) {
+ const TemplateSubstitution ts(tmplate.argName(), instName, *this);
// substitute template in arguments
ArgumentList expandedArgs = argumentList.expandTemplate(ts);
// do the same for return type
ReturnValue expandedRetVal = returnValue.expandTemplate(ts);
// Now stick in new overload stack with expandedMethodName key
// but note we use the same, unexpanded methodName in overload
- string expandedMethodName = methodName + instName.name;
- methods[expandedMethodName].addOverload(methodName, expandedArgs,
+ string expandedMethodName = methodName + instName.name();
+ methods_[expandedMethodName].addOverload(methodName, expandedArgs,
expandedRetVal, is_const, instName, verbose);
}
} else
// just add overload
- methods[methodName].addOverload(methodName, argumentList, returnValue,
- is_const, Qualified(), verbose);
+ methods_[methodName].addOverload(methodName, argumentList, returnValue,
+ is_const, boost::none, verbose);
}
/* ************************************************************************* */
void Class::erase_serialization() {
- Methods::iterator it = methods.find("serializable");
- if (it != methods.end()) {
+ Methods::iterator it = methods_.find("serializable");
+ if (it != methods_.end()) {
#ifndef WRAP_DISABLE_SERIALIZE
isSerializable = true;
#else
// cout << "Ignoring serializable() flag in class " << name << endl;
#endif
- methods.erase(it);
+ methods_.erase(it);
}
- it = methods.find("serialize");
- if (it != methods.end()) {
+ it = methods_.find("serialize");
+ if (it != methods_.end()) {
#ifndef WRAP_DISABLE_SERIALIZE
isSerializable = true;
hasSerialization = true;
#else
// cout << "Ignoring serialize() flag in class " << name << endl;
#endif
- methods.erase(it);
+ methods_.erase(it);
}
}
@@ -327,31 +372,31 @@ void Class::verifyAll(vector& validTypes, bool& hasSerialiable) const {
// verify all of the function arguments
//TODO:verifyArguments(validTypes, constructor.args_list);
verifyArguments(validTypes, static_methods);
- verifyArguments(validTypes, methods);
+ verifyArguments(validTypes, methods_);
// verify function return types
verifyReturnTypes(validTypes, static_methods);
- verifyReturnTypes(validTypes, methods);
+ verifyReturnTypes(validTypes, methods_);
// verify parents
- if (!qualifiedParent.empty()
- && find(validTypes.begin(), validTypes.end(),
- qualifiedParent.qualifiedName("::")) == validTypes.end())
- throw DependencyMissing(qualifiedParent.qualifiedName("::"),
- qualifiedName("::"));
+ boost::optional parent = qualifiedParent();
+ if (parent
+ && find(validTypes.begin(), validTypes.end(), *parent)
+ == validTypes.end())
+ throw DependencyMissing(*parent, qualifiedName("::"));
}
/* ************************************************************************* */
void Class::appendInheritedMethods(const Class& cls,
const vector& classes) {
- if (!cls.qualifiedParent.empty()) {
+ if (cls.parentClass) {
// Find parent
BOOST_FOREACH(const Class& parent, classes) {
// We found a parent class for our parent, TODO improve !
- if (parent.name == cls.qualifiedParent.name) {
- methods.insert(parent.methods.begin(), parent.methods.end());
+ if (parent.name() == cls.parentClass->name()) {
+ methods_.insert(parent.methods_.begin(), parent.methods_.end());
appendInheritedMethods(parent, classes);
}
}
@@ -361,11 +406,11 @@ void Class::appendInheritedMethods(const Class& cls,
/* ************************************************************************* */
string Class::getTypedef() const {
string result;
- BOOST_FOREACH(Str namesp, namespaces) {
+ BOOST_FOREACH(Str namesp, namespaces()) {
result += ("namespace " + namesp + " { ");
}
- result += ("typedef " + typedefName + " " + name + ";");
- for (size_t i = 0; i < namespaces.size(); ++i) {
+ result += ("typedef " + typedefName + " " + name() + ";");
+ for (size_t i = 0; i < namespaces().size(); ++i) {
result += " }";
}
return result;
@@ -373,15 +418,15 @@ string Class::getTypedef() const {
/* ************************************************************************* */
void Class::comment_fragment(FileWriter& proxyFile) const {
- proxyFile.oss << "%class " << name << ", see Doxygen page for details\n";
+ proxyFile.oss << "%class " << name() << ", see Doxygen page for details\n";
proxyFile.oss
<< "%at http://research.cc.gatech.edu/borg/sites/edu.borg/html/index.html\n";
constructor.comment_fragment(proxyFile);
- if (!methods.empty())
+ if (!methods_.empty())
proxyFile.oss << "%\n%-------Methods-------\n";
- BOOST_FOREACH(const Methods::value_type& name_m, methods)
+ BOOST_FOREACH(const Methods::value_type& name_m, methods_)
name_m.second.comment_fragment(proxyFile);
if (!static_methods.empty())
@@ -393,7 +438,7 @@ void Class::comment_fragment(FileWriter& proxyFile) const {
proxyFile.oss << "%\n%-------Serialization Interface-------\n";
proxyFile.oss << "%string_serialize() : returns string\n";
proxyFile.oss << "%string_deserialize(string serialized) : returns "
- << this->name << "\n";
+ << name() << "\n";
}
proxyFile.oss << "%\n";
@@ -586,12 +631,12 @@ string Class::getSerializationExport() const {
/* ************************************************************************* */
void Class::python_wrapper(FileWriter& wrapperFile) const {
- wrapperFile.oss << "class_<" << name << ">(\"" << name << "\")\n";
- constructor.python_wrapper(wrapperFile, name);
+ wrapperFile.oss << "class_<" << name() << ">(\"" << name() << "\")\n";
+ constructor.python_wrapper(wrapperFile, name());
BOOST_FOREACH(const StaticMethod& m, static_methods | boost::adaptors::map_values)
- m.python_wrapper(wrapperFile, name);
- BOOST_FOREACH(const Method& m, methods | boost::adaptors::map_values)
- m.python_wrapper(wrapperFile, name);
+ m.python_wrapper(wrapperFile, name());
+ BOOST_FOREACH(const Method& m, methods_ | boost::adaptors::map_values)
+ m.python_wrapper(wrapperFile, name());
wrapperFile.oss << ";\n\n";
}
diff --git a/wrap/Class.h b/wrap/Class.h
index 34323b797..8faf7ab77 100644
--- a/wrap/Class.h
+++ b/wrap/Class.h
@@ -19,6 +19,7 @@
#pragma once
+#include "Template.h"
#include "Constructor.h"
#include "Deconstructor.h"
#include "Method.h"
@@ -27,6 +28,7 @@
#include
#include
+#include
#include
#include