wrap_mods_inheritance branch: in progress with inheritance in matlab wrapper

release/4.3a0
Richard Roberts 2012-07-08 12:27:39 +00:00
parent c1ef79722b
commit 3c27daae18
10 changed files with 58 additions and 21 deletions

13
gtsam.h
View File

@ -64,7 +64,18 @@ namespace gtsam {
// base
//*************************************************************************
class LieVector {
class Value {
// Testable
void print(string s) const;
bool equals(const gtsam::Value& expected, double tol) const;
// Manifold
size_t dim() const;
gtsam::Value retract(Vector v) const;
Vector localCoordinates(const gtsam::Value& t2) const;
};
class LieVector : gtsam::Value {
// Standard constructors
LieVector();
LieVector(Vector v);

View File

@ -64,7 +64,7 @@ void Argument::matlab_unwrap(FileWriter& file, const string& matlabName) const {
file.oss << cppType << " " << name << " = unwrap< ";
file.oss << cppType << " >(" << matlabName;
if (is_ptr || is_ref) file.oss << ", \"" << matlabType << "\"";
if (is_ptr || is_ref) file.oss << ", \"ptr_" << matlabType << "\"";
file.oss << ");" << endl;
}

View File

@ -39,9 +39,11 @@ void Class::matlab_proxy(const string& classFile, const string& wrapperName, Fil
// emit class proxy code
// we want our class to inherit the handle class for memory purposes
proxyFile.oss << "classdef " << matlabName << " < handle" << endl;
const string parent = qualifiedParent.empty() ?
"handle" : ::wrap::qualifiedName("", qualifiedParent);
proxyFile.oss << "classdef " << matlabName << " < " << parent << endl;
proxyFile.oss << " properties" << endl;
proxyFile.oss << " self = 0" << endl;
proxyFile.oss << " ptr_" << matlabName << " = 0" << endl;
proxyFile.oss << " end" << endl;
proxyFile.oss << " methods" << endl;
@ -116,10 +118,7 @@ void Class::matlab_proxy(const string& classFile, const string& wrapperName, Fil
/* ************************************************************************* */
string Class::qualifiedName(const string& delim) const {
string result;
BOOST_FOREACH(const string& ns, namespaces)
result += ns + delim;
return result + name;
return ::wrap::qualifiedName(delim, namespaces, name);
}
/* ************************************************************************* */
@ -136,14 +135,14 @@ string Class::pointer_constructor_fragments(FileWriter& proxyFile, FileWriter& w
(uint64_t('r'));
const string matlabName = qualifiedName(), cppName = qualifiedName("::");
const string wrapFunctionName = matlabName + "_constructor_" + boost::lexical_cast<string>(id);
const string wrapFunctionName = matlabName + "_collectorInsert_" + boost::lexical_cast<string>(id);
// MATLAB constructor that assigns pointer to matlab object then calls c++
// function to add the object to the collector.
proxyFile.oss << " if nargin == 2 && isa(varargin{1}, 'uint64') && ";
proxyFile.oss << "varargin{1} == uint64(" << ptr_constructor_key << ")\n";
proxyFile.oss << " obj.self = varargin{2};\n";
proxyFile.oss << " " << wrapperName << "(obj.self);\n";
proxyFile.oss << " " << wrapperName << "(" << id << ", obj.self);\n";
// 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

View File

@ -38,6 +38,7 @@ struct Class {
// Then the instance variables are set directly by the Module constructor
std::string name; ///< Class name
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
StaticMethods static_methods; ///< Static methods
std::vector<std::string> namespaces; ///< Stack of namespaces

View File

@ -43,7 +43,7 @@ void Method::proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperF
const vector<string>& using_namespaces,
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) {
const ArgumentList& args = argLists[overload];
@ -74,7 +74,7 @@ void Method::proxy_wrapper_fragments(FileWriter& proxyFile, FileWriter& wrapperF
output = "";
else
output = "varargout{1} = ";
proxyFile.oss << " " << output << wrapperName << "(" << id << ", self, varargin{:});\n";
proxyFile.oss << " " << output << wrapperName << "(" << id << ", this, varargin{:});\n";
// Output C++ wrapper code
@ -135,7 +135,7 @@ string Method::wrapper_fragment(FileWriter& file,
// get class pointer
// 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
args.matlab_unwrap(file,1);

View File

@ -93,7 +93,7 @@ Module::Module(const string& interfacePath,
Rule eigenType_p =
(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;
@ -114,6 +114,10 @@ Module::Module(const string& interfacePath,
className_p[assign_a(arg.type)] >>
(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 argument_p =
@ -198,7 +202,7 @@ Module::Module(const string& interfacePath,
(!*include_p
>> str_p("class")[push_back_a(cls.includes, include_path)][assign_a(include_path, null_str)]
>> 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)
>> str_p("};"))
[assign_a(constructor.name, cls.name)]

View File

@ -342,9 +342,14 @@ gtsam::Matrix unwrap< gtsam::Matrix >(const mxArray* array) {
[create_object] creates a MATLAB proxy class object with a mexhandle
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
invoke the proxy class constructor by calling MATLAB, and pass 13
dummy arguments to let the constructor know we want an object without
the self property initialized. We then assign the mexhandle to self.
invoke the proxy class constructor by calling MATLAB with a special
uint64 value ptr_constructor_key and the pointer itself. MATLAB
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 *result;
@ -376,9 +381,9 @@ mxArray* wrap_shared_ptr(boost::shared_ptr< Class >* shared_ptr, const char *cla
}
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);
if (mxGetClassID(mxh) != mxUINT32OR64_CLASS || mxIsComplex(mxh)
|| mxGetM(mxh) != 1 || mxGetN(mxh) != 1) error(
"Parameter is not an Shared type.");

View File

@ -135,6 +135,17 @@ void generateIncludes(FileWriter& file, const string& class_name,
}
/* ************************************************************************* */
string qualifiedName(const string& separator, const vector<string>& names, const string& finalName) {
string result;
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);
return result;
}
/* ************************************************************************* */
} // \namespace wrap

View File

@ -98,4 +98,10 @@ void generateUsingNamespace(FileWriter& file, const std::vector<std::string>& us
void generateIncludes(FileWriter& file, const std::string& class_name,
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