Added codegen for namespace handling, examples exercising namespaces
parent
aa2eccbcb4
commit
48a2056020
|
@ -33,16 +33,19 @@ void Class::matlab_proxy(const string& classFile) {
|
|||
if(!ofs) throw CantOpenFile(classFile);
|
||||
if(verbose_) cerr << "generating " << classFile << endl;
|
||||
|
||||
// get the name of actual matlab object
|
||||
string matlabName = qualifiedName();
|
||||
|
||||
// emit class proxy code
|
||||
ofs << "classdef " << name << endl;
|
||||
ofs << "classdef " << matlabName << endl;
|
||||
ofs << " properties" << endl;
|
||||
ofs << " self = 0" << endl;
|
||||
ofs << " end" << endl;
|
||||
ofs << " methods" << endl;
|
||||
ofs << " function obj = " << name << "(varargin)" << endl;
|
||||
ofs << " function obj = " << matlabName << "(varargin)" << endl;
|
||||
BOOST_FOREACH(Constructor c, constructors)
|
||||
c.matlab_proxy_fragment(ofs,name);
|
||||
ofs << " if nargin ~= 13 && obj.self == 0, error('" << name << " constructor failed'); end" << endl;
|
||||
c.matlab_proxy_fragment(ofs,matlabName);
|
||||
ofs << " if nargin ~= 13 && obj.self == 0, error('" << matlabName << " constructor failed'); end" << endl;
|
||||
ofs << " end" << endl;
|
||||
ofs << " function display(obj), obj.print(''); end" << endl;
|
||||
ofs << " function disp(obj), obj.display; end" << endl;
|
||||
|
@ -56,24 +59,26 @@ void Class::matlab_proxy(const string& classFile) {
|
|||
/* ************************************************************************* */
|
||||
void Class::matlab_constructors(const string& toolboxPath,const string& nameSpace) {
|
||||
BOOST_FOREACH(Constructor c, constructors) {
|
||||
c.matlab_mfile (toolboxPath, name);
|
||||
c.matlab_wrapper(toolboxPath, name, nameSpace);
|
||||
c.matlab_mfile (toolboxPath, qualifiedName());
|
||||
c.matlab_wrapper(toolboxPath, qualifiedName("::"), qualifiedName(), nameSpace);
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Class::matlab_methods(const string& classPath, const string& nameSpace) {
|
||||
string matlabName = qualifiedName(), cppName = qualifiedName("::");
|
||||
BOOST_FOREACH(Method m, methods) {
|
||||
m.matlab_mfile (classPath);
|
||||
m.matlab_wrapper(classPath, name, nameSpace);
|
||||
m.matlab_wrapper(classPath, name, cppName, matlabName, nameSpace);
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Class::matlab_static_methods(const string& toolboxPath, const string& nameSpace) {
|
||||
string matlabName = qualifiedName(), cppName = qualifiedName("::");
|
||||
BOOST_FOREACH(StaticMethod& m, static_methods) {
|
||||
m.matlab_mfile (toolboxPath, name);
|
||||
m.matlab_wrapper(toolboxPath, name, nameSpace);
|
||||
m.matlab_mfile (toolboxPath, qualifiedName());
|
||||
m.matlab_wrapper(toolboxPath, name, matlabName, cppName, nameSpace);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -83,13 +88,14 @@ void Class::matlab_make_fragment(ofstream& ofs,
|
|||
const string& mexFlags)
|
||||
{
|
||||
string mex = "mex " + mexFlags + " ";
|
||||
string matlabClassName = qualifiedName();
|
||||
BOOST_FOREACH(Constructor c, constructors)
|
||||
ofs << mex << c.matlab_wrapper_name(name) << ".cpp" << endl;
|
||||
ofs << mex << c.matlab_wrapper_name(matlabClassName) << ".cpp" << endl;
|
||||
BOOST_FOREACH(StaticMethod sm, static_methods)
|
||||
ofs << mex << name + "_" + sm.name << ".cpp" << endl;
|
||||
ofs << endl << "cd @" << name << endl;
|
||||
ofs << mex << matlabClassName + "_" + sm.name << ".cpp" << endl;
|
||||
ofs << endl << "cd @" << matlabClassName << endl;
|
||||
BOOST_FOREACH(Method m, methods)
|
||||
ofs << mex << m.name_ << ".cpp" << endl;
|
||||
ofs << mex << m.name << ".cpp" << endl;
|
||||
ofs << endl;
|
||||
}
|
||||
|
||||
|
@ -108,18 +114,20 @@ void Class::makefile_fragment(ofstream& ofs) {
|
|||
//
|
||||
// Point2: new_Point2_.$(MEXENDING) new_Point2_dd.$(MEXENDING) @Point2/x.$(MEXENDING) @Point2/y.$(MEXENDING) @Point2/dim.$(MEXENDING)
|
||||
|
||||
string matlabName = qualifiedName();
|
||||
|
||||
// collect names
|
||||
vector<string> file_names;
|
||||
BOOST_FOREACH(Constructor c, constructors) {
|
||||
string file_base = c.matlab_wrapper_name(name);
|
||||
string file_base = c.matlab_wrapper_name(matlabName);
|
||||
file_names.push_back(file_base);
|
||||
}
|
||||
BOOST_FOREACH(StaticMethod c, static_methods) {
|
||||
string file_base = name + "_" + c.name;
|
||||
string file_base = matlabName + "_" + c.name;
|
||||
file_names.push_back(file_base);
|
||||
}
|
||||
BOOST_FOREACH(Method c, methods) {
|
||||
string file_base = "@" + name + "/" + c.name_;
|
||||
string file_base = "@" + matlabName + "/" + c.name;
|
||||
file_names.push_back(file_base);
|
||||
}
|
||||
|
||||
|
@ -129,7 +137,7 @@ void Class::makefile_fragment(ofstream& ofs) {
|
|||
}
|
||||
|
||||
// class target
|
||||
ofs << "\n" << name << ": ";
|
||||
ofs << "\n" << matlabName << ": ";
|
||||
BOOST_FOREACH(const string& file_base, file_names) {
|
||||
ofs << file_base << ".$(MEXENDING) ";
|
||||
}
|
||||
|
@ -137,3 +145,11 @@ void Class::makefile_fragment(ofstream& ofs) {
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
string Class::qualifiedName(const string& delim) const {
|
||||
string result;
|
||||
BOOST_FOREACH(const string& ns, namespaces)
|
||||
result += ns + delim;
|
||||
return result + name;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
#include "Constructor.h"
|
||||
#include "Method.h"
|
||||
|
@ -33,9 +32,9 @@ struct Class {
|
|||
|
||||
// Then the instance variables are set directly by the Module constructor
|
||||
std::string name; ///< Class name
|
||||
std::list<Constructor> constructors; ///< Class constructors
|
||||
std::list<Method> methods; ///< Class methods
|
||||
std::list<StaticMethod> static_methods; ///< Static methods
|
||||
std::vector<Constructor> constructors; ///< Class constructors
|
||||
std::vector<Method> methods; ///< Class methods
|
||||
std::vector<StaticMethod> static_methods; ///< Static methods
|
||||
std::vector<std::string> namespaces; ///< Stack of namespaces
|
||||
bool verbose_; ///< verbose flag
|
||||
|
||||
|
@ -51,6 +50,7 @@ struct Class {
|
|||
const std::string& toolboxPath,
|
||||
const std::string& mexFlags); ///< emit make fragment for global make script
|
||||
void makefile_fragment(std::ofstream& ofs); ///< emit makefile fragment
|
||||
std::string qualifiedName(const std::string& delim = "") const; ///< creates a namespace-qualified name, optional delimiter
|
||||
};
|
||||
|
||||
} // \namespace wrap
|
||||
|
|
|
@ -45,22 +45,22 @@ void Constructor::matlab_proxy_fragment(ofstream& ofs, const string& className)
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Constructor::matlab_mfile(const string& toolboxPath, const string& className) {
|
||||
void Constructor::matlab_mfile(const string& toolboxPath, const string& qualifiedMatlabName) {
|
||||
|
||||
string name = matlab_wrapper_name(className);
|
||||
string matlabName = matlab_wrapper_name(qualifiedMatlabName);
|
||||
|
||||
// open destination m-file
|
||||
string wrapperFile = toolboxPath + "/" + name + ".m";
|
||||
string wrapperFile = toolboxPath + "/" + matlabName + ".m";
|
||||
ofstream ofs(wrapperFile.c_str());
|
||||
if(!ofs) throw CantOpenFile(wrapperFile);
|
||||
if(verbose_) cerr << "generating " << wrapperFile << endl;
|
||||
|
||||
// generate code
|
||||
wrap::emit_header_comment(ofs, "%");
|
||||
ofs << "function result = " << name << "(obj";
|
||||
ofs << "function result = " << matlabName << "(obj";
|
||||
if (args.size()) ofs << "," << args.names();
|
||||
ofs << ")" << endl;
|
||||
ofs << " error('need to compile " << name << ".cpp');" << endl;
|
||||
ofs << " error('need to compile " << matlabName << ".cpp');" << endl;
|
||||
ofs << "end" << endl;
|
||||
|
||||
// close file
|
||||
|
@ -68,15 +68,16 @@ void Constructor::matlab_mfile(const string& toolboxPath, const string& classNam
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Constructor::matlab_wrapper(const string& toolboxPath,
|
||||
const string& className,
|
||||
void Constructor::matlab_wrapper(const string& toolboxPath,
|
||||
const string& cppClassName,
|
||||
const string& matlabClassName,
|
||||
const string& nameSpace)
|
||||
{
|
||||
|
||||
string name = matlab_wrapper_name(className);
|
||||
string matlabName = matlab_wrapper_name(matlabClassName);
|
||||
|
||||
// open destination wrapperFile
|
||||
string wrapperFile = toolboxPath + "/" + name + ".cpp";
|
||||
string wrapperFile = toolboxPath + "/" + matlabName + ".cpp";
|
||||
ofstream ofs(wrapperFile.c_str());
|
||||
if(!ofs) throw CantOpenFile(wrapperFile);
|
||||
if(verbose_) cerr << "generating " << wrapperFile << endl;
|
||||
|
@ -84,14 +85,14 @@ void Constructor::matlab_wrapper(const string& toolboxPath,
|
|||
// generate code
|
||||
wrap::emit_header_comment(ofs, "//");
|
||||
ofs << "#include <wrap/matlab.h>" << endl;
|
||||
ofs << "#include <" << className << ".h>" << endl;
|
||||
ofs << "#include <" << name << ".h>" << endl;
|
||||
if (!nameSpace.empty()) ofs << "using namespace " << nameSpace << ";" << endl;
|
||||
ofs << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl;
|
||||
ofs << "{" << endl;
|
||||
ofs << " checkArguments(\"" << name << "\",nargout,nargin," << args.size() << ");" << endl;
|
||||
ofs << " checkArguments(\"" << matlabName << "\",nargout,nargin," << args.size() << ");" << endl;
|
||||
args.matlab_unwrap(ofs); // unwrap arguments
|
||||
ofs << " " << className << "* self = new " << className << "(" << args.names() << ");" << endl;
|
||||
ofs << " out[0] = wrap_constructed(self,\"" << className << "\");" << endl;
|
||||
ofs << " " << cppClassName << "* self = new " << cppClassName << "(" << args.names() << ");" << endl; // need qualified name, delim: "::"
|
||||
ofs << " out[0] = wrap_constructed(self,\"" << matlabClassName << "\");" << endl; // need matlab qualified name
|
||||
ofs << "}" << endl;
|
||||
|
||||
// close file
|
||||
|
|
|
@ -34,6 +34,7 @@ struct Constructor {
|
|||
|
||||
// Then the instance variables are set directly by the Module constructor
|
||||
ArgumentList args;
|
||||
std::string name;
|
||||
bool verbose_;
|
||||
|
||||
// MATLAB code generation
|
||||
|
@ -48,11 +49,13 @@ struct Constructor {
|
|||
|
||||
/// m-file
|
||||
void matlab_mfile(const std::string& toolboxPath,
|
||||
const std::string& className);
|
||||
const std::string& qualifiedMatlabName);
|
||||
|
||||
/// wrapper
|
||||
void matlab_wrapper(const std::string& toolboxPath,
|
||||
const std::string& className, const std::string& nameSpace);
|
||||
const std::string& cppClassName,
|
||||
const std::string& matlabClassName,
|
||||
const std::string& nameSpace);
|
||||
};
|
||||
|
||||
} // \namespace wrap
|
||||
|
|
|
@ -29,18 +29,18 @@ using namespace wrap;
|
|||
void Method::matlab_mfile(const string& classPath) {
|
||||
|
||||
// open destination m-file
|
||||
string wrapperFile = classPath + "/" + name_ + ".m";
|
||||
string wrapperFile = classPath + "/" + name + ".m";
|
||||
ofstream ofs(wrapperFile.c_str());
|
||||
if(!ofs) throw CantOpenFile(wrapperFile);
|
||||
if(verbose_) cerr << "generating " << wrapperFile << endl;
|
||||
|
||||
// generate code
|
||||
string returnType = returnVal_.matlab_returnType();
|
||||
ofs << "function " << returnType << " = " << name_ << "(obj";
|
||||
if (args_.size()) ofs << "," << args_.names();
|
||||
string returnType = returnVal.matlab_returnType();
|
||||
ofs << "function " << returnType << " = " << name << "(obj";
|
||||
if (args.size()) ofs << "," << args.names();
|
||||
ofs << ")" << endl;
|
||||
ofs << "% usage: obj." << name_ << "(" << args_.names() << ")" << endl;
|
||||
ofs << " error('need to compile " << name_ << ".cpp');" << endl;
|
||||
ofs << "% usage: obj." << name << "(" << args.names() << ")" << endl;
|
||||
ofs << " error('need to compile " << name << ".cpp');" << endl;
|
||||
ofs << "end" << endl;
|
||||
|
||||
// close file
|
||||
|
@ -50,10 +50,12 @@ void Method::matlab_mfile(const string& classPath) {
|
|||
/* ************************************************************************* */
|
||||
void Method::matlab_wrapper(const string& classPath,
|
||||
const string& className,
|
||||
const string& cppClassName,
|
||||
const string& matlabClassName,
|
||||
const string& nameSpace)
|
||||
{
|
||||
// open destination wrapperFile
|
||||
string wrapperFile = classPath + "/" + name_ + ".cpp";
|
||||
string wrapperFile = classPath + "/" + name + ".cpp";
|
||||
ofstream ofs(wrapperFile.c_str());
|
||||
if(!ofs) throw CantOpenFile(wrapperFile);
|
||||
if(verbose_) cerr << "generating " << wrapperFile << endl;
|
||||
|
@ -74,26 +76,26 @@ void Method::matlab_wrapper(const string& classPath,
|
|||
// check arguments
|
||||
// extra argument obj -> nargin-1 is passed !
|
||||
// example: checkArguments("equals",nargout,nargin-1,2);
|
||||
ofs << " checkArguments(\"" << name_ << "\",nargout,nargin-1," << args_.size() << ");\n";
|
||||
ofs << " checkArguments(\"" << name << "\",nargout,nargin-1," << args.size() << ");\n";
|
||||
|
||||
// get class pointer
|
||||
// example: shared_ptr<Test> = unwrap_shared_ptr< Test >(in[0], "Test");
|
||||
ofs << " shared_ptr<" << className << "> self = unwrap_shared_ptr< " << className
|
||||
<< " >(in[0],\"" << className << "\");" << endl;
|
||||
ofs << " shared_ptr<" << cppClassName << "> self = unwrap_shared_ptr< " << cppClassName
|
||||
<< " >(in[0],\"" << matlabClassName << "\");" << endl;
|
||||
|
||||
// unwrap arguments, see Argument.cpp
|
||||
args_.matlab_unwrap(ofs,1);
|
||||
args.matlab_unwrap(ofs,1);
|
||||
|
||||
// call method
|
||||
// example: bool result = self->return_field(t);
|
||||
ofs << " ";
|
||||
if (returnVal_.type1!="void")
|
||||
ofs << returnVal_.return_type(true,ReturnValue::pair) << " result = ";
|
||||
ofs << "self->" << name_ << "(" << args_.names() << ");\n";
|
||||
if (returnVal.type1!="void")
|
||||
ofs << returnVal.return_type(true,ReturnValue::pair) << " result = ";
|
||||
ofs << "self->" << name << "(" << args.names() << ");\n";
|
||||
|
||||
// wrap result
|
||||
// example: out[0]=wrap<bool>(result);
|
||||
returnVal_.wrap_result(ofs);
|
||||
returnVal.wrap_result(ofs);
|
||||
|
||||
// finish
|
||||
ofs << "}\n";
|
||||
|
|
|
@ -35,16 +35,18 @@ struct Method {
|
|||
// Then the instance variables are set directly by the Module constructor
|
||||
bool verbose_;
|
||||
bool is_const_;
|
||||
std::string name_;
|
||||
ArgumentList args_;
|
||||
ReturnValue returnVal_;
|
||||
std::string name;
|
||||
ArgumentList args;
|
||||
ReturnValue returnVal;
|
||||
|
||||
// MATLAB code generation
|
||||
// classPath is class directory, e.g., ../matlab/@Point2
|
||||
|
||||
void matlab_mfile(const std::string& classPath); ///< m-file
|
||||
void matlab_wrapper(const std::string& classPath,
|
||||
const std::string& className, const std::string& nameSpace); ///< wrapper
|
||||
const std::string& className,
|
||||
const std::string& cppClassName,
|
||||
const std::string& matlabClassname,const std::string& nameSpace); ///< wrapper
|
||||
};
|
||||
|
||||
} // \namespace wrap
|
||||
|
|
|
@ -104,6 +104,7 @@ Module::Module(const string& interfacePath,
|
|||
Rule constructor_p =
|
||||
(className_p >> '(' >> argumentList_p >> ')' >> ';' >> !comments_p)
|
||||
[assign_a(constructor.args,args)]
|
||||
[assign_a(constructor.name,cls.name)]
|
||||
[assign_a(args,args0)]
|
||||
[push_back_a(cls.constructors, constructor)]
|
||||
[assign_a(constructor,constructor0)];
|
||||
|
@ -131,12 +132,12 @@ Module::Module(const string& interfacePath,
|
|||
Rule methodName_p = lexeme_d[lower_p >> *(alnum_p | '_')];
|
||||
|
||||
Rule method_p =
|
||||
(returnType_p >> methodName_p[assign_a(method.name_)] >>
|
||||
(returnType_p >> methodName_p[assign_a(method.name)] >>
|
||||
'(' >> argumentList_p >> ')' >>
|
||||
!str_p("const")[assign_a(method.is_const_,true)] >> ';' >> *comments_p)
|
||||
[assign_a(method.args_,args)]
|
||||
[assign_a(method.args,args)]
|
||||
[assign_a(args,args0)]
|
||||
[assign_a(method.returnVal_,retVal)]
|
||||
[assign_a(method.returnVal,retVal)]
|
||||
[assign_a(retVal,retVal0)]
|
||||
[push_back_a(cls.methods, method)]
|
||||
[assign_a(method,method0)];
|
||||
|
@ -165,7 +166,7 @@ Module::Module(const string& interfacePath,
|
|||
namespace_name_p[push_back_a(namespaces)]
|
||||
>> ch_p('{') >>
|
||||
*(class_p | namespace_p | comments_p) >>
|
||||
str_p("}///\\namespace") // end namespace, avoid confusion with classes
|
||||
str_p("}///\\namespace") >> !namespace_name_p // end namespace, avoid confusion with classes
|
||||
[pop_a(namespaces)];
|
||||
|
||||
Rule module_content_p = comments_p | class_p | namespace_p ;
|
||||
|
@ -207,6 +208,18 @@ Module::Module(const string& interfacePath,
|
|||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void verifyArguments(const vector<string>& validArgs, const vector<T>& vt) {
|
||||
BOOST_FOREACH(const T& t, vt) {
|
||||
BOOST_FOREACH(Argument arg, t.args) {
|
||||
if(std::find(validArgs.begin(), validArgs.end(), arg.type)
|
||||
== validArgs.end())
|
||||
throw DependencyMissing(arg.type, t.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Module::matlab_code(const string& toolboxPath,
|
||||
const string& nameSpace,
|
||||
|
@ -254,60 +267,40 @@ void Module::matlab_code(const string& toolboxPath,
|
|||
// add 'all' to Makefile
|
||||
make_ofs << "all: ";
|
||||
BOOST_FOREACH(Class cls, classes) {
|
||||
make_ofs << cls.name << " ";
|
||||
//Create a list of parsed classes for dependency checking
|
||||
validArgs.push_back(cls.name);
|
||||
make_ofs << cls.qualifiedName() << " ";
|
||||
//Create a list of parsed classes for dependency checking
|
||||
validArgs.push_back(cls.name);
|
||||
}
|
||||
make_ofs << "\n\n";
|
||||
|
||||
|
||||
|
||||
// generate proxy classes and wrappers
|
||||
BOOST_FOREACH(Class cls, classes) {
|
||||
// create directory if needed
|
||||
string classPath = toolboxPath + "/@" + cls.name;
|
||||
string classPath = toolboxPath + "/@" + cls.qualifiedName();
|
||||
string installCmd = "install -d " + classPath;
|
||||
system(installCmd.c_str());
|
||||
|
||||
// create proxy class
|
||||
string classFile = classPath + "/" + cls.name + ".m";
|
||||
string classFile = classPath + "/" + cls.qualifiedName() + ".m";
|
||||
cls.matlab_proxy(classFile);
|
||||
|
||||
// create constructor and method wrappers
|
||||
BOOST_FOREACH(Constructor con, cls.constructors) {
|
||||
BOOST_FOREACH(Argument arg, con.args) {
|
||||
if(std::find(validArgs.begin(), validArgs.end(), arg.type)
|
||||
== validArgs.end())
|
||||
throw DependencyMissing(arg.type, cls.name);
|
||||
}
|
||||
}
|
||||
cls.matlab_constructors(toolboxPath,nameSpace);
|
||||
|
||||
BOOST_FOREACH(StaticMethod stMth, cls.static_methods) {
|
||||
BOOST_FOREACH(Argument arg, stMth.args) {
|
||||
if(std::find(validArgs.begin(), validArgs.end(), arg.type)
|
||||
== validArgs.end())
|
||||
throw DependencyMissing(arg.type, stMth.name);
|
||||
}
|
||||
}
|
||||
cls.matlab_static_methods(toolboxPath,nameSpace);
|
||||
// verify all of the function arguments
|
||||
verifyArguments<Constructor>(validArgs, cls.constructors);
|
||||
verifyArguments<StaticMethod>(validArgs, cls.static_methods);
|
||||
verifyArguments<Method>(validArgs, cls.methods);
|
||||
|
||||
BOOST_FOREACH(Method mth, cls.methods) {
|
||||
BOOST_FOREACH(Argument arg, mth.args_) {
|
||||
if(std::find(validArgs.begin(), validArgs.end(), arg.type)
|
||||
== validArgs.end())
|
||||
throw DependencyMissing(arg.type, mth.name_);
|
||||
}
|
||||
}
|
||||
// create constructor and method wrappers
|
||||
cls.matlab_constructors(toolboxPath,nameSpace);
|
||||
cls.matlab_static_methods(toolboxPath,nameSpace);
|
||||
cls.matlab_methods(classPath,nameSpace);
|
||||
|
||||
// add lines to make m-file
|
||||
ofs << "%% " << cls.name << endl;
|
||||
ofs << "%% " << cls.qualifiedName() << endl;
|
||||
ofs << "cd(toolboxpath)" << endl;
|
||||
cls.matlab_make_fragment(ofs, toolboxPath, mexFlags);
|
||||
|
||||
// add section to the (actual) make file
|
||||
make_ofs << "# " << cls.name << endl;
|
||||
make_ofs << "# " << cls.qualifiedName() << endl;
|
||||
cls.makefile_fragment(make_ofs);
|
||||
}
|
||||
|
||||
|
@ -320,7 +313,7 @@ void Module::matlab_code(const string& toolboxPath,
|
|||
make_ofs << "\n\nclean: \n";
|
||||
make_ofs << "\trm -rf *.$(MEXENDING)\n";
|
||||
BOOST_FOREACH(Class cls, classes)
|
||||
make_ofs << "\trm -rf @" << cls.name << "/*.$(MEXENDING)\n";
|
||||
make_ofs << "\trm -rf @" << cls.qualifiedName() << "/*.$(MEXENDING)\n";
|
||||
|
||||
// finish Makefile
|
||||
make_ofs << "\n" << endl;
|
||||
|
|
|
@ -49,11 +49,11 @@ void StaticMethod::matlab_mfile(const string& toolboxPath, const string& classNa
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void StaticMethod::matlab_wrapper(const string& toolboxPath,
|
||||
const string& className, const string& nameSpace)
|
||||
void StaticMethod::matlab_wrapper(const string& toolboxPath, const string& className,
|
||||
const string& matlabClassName, const string& cppClassName, const string& nameSpace)
|
||||
{
|
||||
// open destination wrapperFile
|
||||
string full_name = className + "_" + name;
|
||||
string full_name = matlabClassName + "_" + name;
|
||||
string wrapperFile = toolboxPath + "/" + full_name + ".cpp";
|
||||
ofstream ofs(wrapperFile.c_str());
|
||||
if(!ofs) throw CantOpenFile(wrapperFile);
|
||||
|
@ -84,7 +84,7 @@ void StaticMethod::matlab_wrapper(const string& toolboxPath,
|
|||
// call method with default type
|
||||
if (returnVal.type1!="void")
|
||||
ofs << returnVal.return_type(true,ReturnValue::pair) << " result = ";
|
||||
ofs << className << "::" << name << "(" << args.names() << ");\n";
|
||||
ofs << cppClassName << "::" << name << "(" << args.names() << ");\n";
|
||||
|
||||
// wrap result
|
||||
// example: out[0]=wrap<bool>(result);
|
||||
|
|
|
@ -46,7 +46,8 @@ struct StaticMethod {
|
|||
|
||||
void matlab_mfile(const std::string& toolboxPath, const std::string& className); ///< m-file
|
||||
void matlab_wrapper(const std::string& toolboxPath,
|
||||
const std::string& className, const std::string& nameSpace); ///< wrapper
|
||||
const std::string& className, const std::string& matlabClassName,
|
||||
const std::string& cppClassName, const std::string& nameSpace); ///< cpp wrapper
|
||||
};
|
||||
|
||||
} // \namespace wrap
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
classdef ClassD
|
||||
properties
|
||||
self = 0
|
||||
end
|
||||
methods
|
||||
function obj = ClassD(varargin)
|
||||
if nargin == 0, obj.self = new_ClassD_(); end
|
||||
if nargin ~= 13 && obj.self == 0, error('ClassD constructor failed'); end
|
||||
end
|
||||
function display(obj), obj.print(''); end
|
||||
function disp(obj), obj.display; end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
classdef ns1ClassA
|
||||
properties
|
||||
self = 0
|
||||
end
|
||||
methods
|
||||
function obj = ns1ClassA(varargin)
|
||||
if nargin == 0, obj.self = new_ns1ClassA_(); end
|
||||
if nargin ~= 13 && obj.self == 0, error('ns1ClassA constructor failed'); end
|
||||
end
|
||||
function display(obj), obj.print(''); end
|
||||
function disp(obj), obj.display; end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
classdef ns1ClassB
|
||||
properties
|
||||
self = 0
|
||||
end
|
||||
methods
|
||||
function obj = ns1ClassB(varargin)
|
||||
if nargin == 0, obj.self = new_ns1ClassB_(); end
|
||||
if nargin ~= 13 && obj.self == 0, error('ns1ClassB constructor failed'); end
|
||||
end
|
||||
function display(obj), obj.print(''); end
|
||||
function disp(obj), obj.display; end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
// automatically generated by wrap on 2011-Dec-08
|
||||
#include <wrap/matlab.h>
|
||||
#include <ClassA.h>
|
||||
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
|
||||
{
|
||||
checkArguments("memberFunction",nargout,nargin-1,0);
|
||||
shared_ptr<ns2::ClassA> self = unwrap_shared_ptr< ns2::ClassA >(in[0],"ns2ClassA");
|
||||
double result = self->memberFunction();
|
||||
out[0] = wrap< double >(result);
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
function result = memberFunction(obj)
|
||||
% usage: obj.memberFunction()
|
||||
error('need to compile memberFunction.cpp');
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
classdef ns2ClassA
|
||||
properties
|
||||
self = 0
|
||||
end
|
||||
methods
|
||||
function obj = ns2ClassA(varargin)
|
||||
if nargin == 0, obj.self = new_ns2ClassA_(); end
|
||||
if nargin ~= 13 && obj.self == 0, error('ns2ClassA constructor failed'); end
|
||||
end
|
||||
function display(obj), obj.print(''); end
|
||||
function disp(obj), obj.display; end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
classdef ns2ClassC
|
||||
properties
|
||||
self = 0
|
||||
end
|
||||
methods
|
||||
function obj = ns2ClassC(varargin)
|
||||
if nargin == 0, obj.self = new_ns2ClassC_(); end
|
||||
if nargin ~= 13 && obj.self == 0, error('ns2ClassC constructor failed'); end
|
||||
end
|
||||
function display(obj), obj.print(''); end
|
||||
function disp(obj), obj.display; end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
classdef ns2ns3ClassB
|
||||
properties
|
||||
self = 0
|
||||
end
|
||||
methods
|
||||
function obj = ns2ns3ClassB(varargin)
|
||||
if nargin == 0, obj.self = new_ns2ns3ClassB_(); end
|
||||
if nargin ~= 13 && obj.self == 0, error('ns2ns3ClassB constructor failed'); end
|
||||
end
|
||||
function display(obj), obj.print(''); end
|
||||
function disp(obj), obj.display; end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,60 @@
|
|||
# automatically generated by wrap on 2011-Dec-08
|
||||
|
||||
MEX = mex
|
||||
MEXENDING = mexa64
|
||||
mex_flags = -O5
|
||||
|
||||
all: ns1ClassA ns1ClassB ns2ClassA ns2ns3ClassB ns2ClassC ClassD
|
||||
|
||||
# ns1ClassA
|
||||
new_ns1ClassA_.$(MEXENDING): new_ns1ClassA_.cpp
|
||||
$(MEX) $(mex_flags) new_ns1ClassA_.cpp -output new_ns1ClassA_
|
||||
|
||||
ns1ClassA: new_ns1ClassA_.$(MEXENDING)
|
||||
|
||||
# ns1ClassB
|
||||
new_ns1ClassB_.$(MEXENDING): new_ns1ClassB_.cpp
|
||||
$(MEX) $(mex_flags) new_ns1ClassB_.cpp -output new_ns1ClassB_
|
||||
|
||||
ns1ClassB: new_ns1ClassB_.$(MEXENDING)
|
||||
|
||||
# ns2ClassA
|
||||
new_ns2ClassA_.$(MEXENDING): new_ns2ClassA_.cpp
|
||||
$(MEX) $(mex_flags) new_ns2ClassA_.cpp -output new_ns2ClassA_
|
||||
ns2ClassA_afunction.$(MEXENDING): ns2ClassA_afunction.cpp
|
||||
$(MEX) $(mex_flags) ns2ClassA_afunction.cpp -output ns2ClassA_afunction
|
||||
@ns2ClassA/memberFunction.$(MEXENDING): @ns2ClassA/memberFunction.cpp
|
||||
$(MEX) $(mex_flags) @ns2ClassA/memberFunction.cpp -output @ns2ClassA/memberFunction
|
||||
|
||||
ns2ClassA: new_ns2ClassA_.$(MEXENDING) ns2ClassA_afunction.$(MEXENDING) @ns2ClassA/memberFunction.$(MEXENDING)
|
||||
|
||||
# ns2ns3ClassB
|
||||
new_ns2ns3ClassB_.$(MEXENDING): new_ns2ns3ClassB_.cpp
|
||||
$(MEX) $(mex_flags) new_ns2ns3ClassB_.cpp -output new_ns2ns3ClassB_
|
||||
|
||||
ns2ns3ClassB: new_ns2ns3ClassB_.$(MEXENDING)
|
||||
|
||||
# ns2ClassC
|
||||
new_ns2ClassC_.$(MEXENDING): new_ns2ClassC_.cpp
|
||||
$(MEX) $(mex_flags) new_ns2ClassC_.cpp -output new_ns2ClassC_
|
||||
|
||||
ns2ClassC: new_ns2ClassC_.$(MEXENDING)
|
||||
|
||||
# ClassD
|
||||
new_ClassD_.$(MEXENDING): new_ClassD_.cpp
|
||||
$(MEX) $(mex_flags) new_ClassD_.cpp -output new_ClassD_
|
||||
|
||||
ClassD: new_ClassD_.$(MEXENDING)
|
||||
|
||||
|
||||
|
||||
clean:
|
||||
rm -rf *.$(MEXENDING)
|
||||
rm -rf @ns1ClassA/*.$(MEXENDING)
|
||||
rm -rf @ns1ClassB/*.$(MEXENDING)
|
||||
rm -rf @ns2ClassA/*.$(MEXENDING)
|
||||
rm -rf @ns2ns3ClassB/*.$(MEXENDING)
|
||||
rm -rf @ns2ClassC/*.$(MEXENDING)
|
||||
rm -rf @ClassD/*.$(MEXENDING)
|
||||
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
% automatically generated by wrap on 2011-Dec-08
|
||||
echo on
|
||||
|
||||
toolboxpath = mfilename('fullpath');
|
||||
delims = find(toolboxpath == '/');
|
||||
toolboxpath = toolboxpath(1:(delims(end)-1));
|
||||
clear delims
|
||||
addpath(toolboxpath);
|
||||
|
||||
%% ns1ClassA
|
||||
cd(toolboxpath)
|
||||
mex -O5 new_ns1ClassA_.cpp
|
||||
|
||||
cd @ns1ClassA
|
||||
|
||||
%% ns1ClassB
|
||||
cd(toolboxpath)
|
||||
mex -O5 new_ns1ClassB_.cpp
|
||||
|
||||
cd @ns1ClassB
|
||||
|
||||
%% ns2ClassA
|
||||
cd(toolboxpath)
|
||||
mex -O5 new_ns2ClassA_.cpp
|
||||
mex -O5 ns2ClassA_afunction.cpp
|
||||
|
||||
cd @ns2ClassA
|
||||
mex -O5 memberFunction.cpp
|
||||
|
||||
%% ns2ns3ClassB
|
||||
cd(toolboxpath)
|
||||
mex -O5 new_ns2ns3ClassB_.cpp
|
||||
|
||||
cd @ns2ns3ClassB
|
||||
|
||||
%% ns2ClassC
|
||||
cd(toolboxpath)
|
||||
mex -O5 new_ns2ClassC_.cpp
|
||||
|
||||
cd @ns2ClassC
|
||||
|
||||
%% ClassD
|
||||
cd(toolboxpath)
|
||||
mex -O5 new_ClassD_.cpp
|
||||
|
||||
cd @ClassD
|
||||
|
||||
cd(toolboxpath)
|
||||
|
||||
echo off
|
|
@ -0,0 +1,9 @@
|
|||
// automatically generated by wrap on 2011-Dec-08
|
||||
#include <wrap/matlab.h>
|
||||
#include <ClassD.h>
|
||||
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
|
||||
{
|
||||
checkArguments("new_ClassD_",nargout,nargin,0);
|
||||
ClassD* self = new ClassD();
|
||||
out[0] = wrap_constructed(self,"ClassD");
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
% automatically generated by wrap on 2011-Dec-08
|
||||
function result = new_ClassD_(obj)
|
||||
error('need to compile new_ClassD_.cpp');
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
// automatically generated by wrap on 2011-Dec-08
|
||||
#include <wrap/matlab.h>
|
||||
#include <ClassA.h>
|
||||
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
|
||||
{
|
||||
checkArguments("new_ns1ClassA_",nargout,nargin,0);
|
||||
ns1::ClassA* self = new ns1::ClassA();
|
||||
out[0] = wrap_constructed(self,"ns1ClassA");
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
% automatically generated by wrap on 2011-Dec-08
|
||||
function result = new_ns1ClassA_(obj)
|
||||
error('need to compile new_ns1ClassA_.cpp');
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
// automatically generated by wrap on 2011-Dec-08
|
||||
#include <wrap/matlab.h>
|
||||
#include <ClassB.h>
|
||||
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
|
||||
{
|
||||
checkArguments("new_ns1ClassB_",nargout,nargin,0);
|
||||
ns1::ClassB* self = new ns1::ClassB();
|
||||
out[0] = wrap_constructed(self,"ns1ClassB");
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
% automatically generated by wrap on 2011-Dec-08
|
||||
function result = new_ns1ClassB_(obj)
|
||||
error('need to compile new_ns1ClassB_.cpp');
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
// automatically generated by wrap on 2011-Dec-08
|
||||
#include <wrap/matlab.h>
|
||||
#include <ClassA.h>
|
||||
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
|
||||
{
|
||||
checkArguments("new_ns2ClassA_",nargout,nargin,0);
|
||||
ns2::ClassA* self = new ns2::ClassA();
|
||||
out[0] = wrap_constructed(self,"ns2ClassA");
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
% automatically generated by wrap on 2011-Dec-08
|
||||
function result = new_ns2ClassA_(obj)
|
||||
error('need to compile new_ns2ClassA_.cpp');
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
// automatically generated by wrap on 2011-Dec-08
|
||||
#include <wrap/matlab.h>
|
||||
#include <ClassC.h>
|
||||
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
|
||||
{
|
||||
checkArguments("new_ns2ClassC_",nargout,nargin,0);
|
||||
ns2::ClassC* self = new ns2::ClassC();
|
||||
out[0] = wrap_constructed(self,"ns2ClassC");
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
% automatically generated by wrap on 2011-Dec-08
|
||||
function result = new_ns2ClassC_(obj)
|
||||
error('need to compile new_ns2ClassC_.cpp');
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
// automatically generated by wrap on 2011-Dec-08
|
||||
#include <wrap/matlab.h>
|
||||
#include <ClassB.h>
|
||||
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
|
||||
{
|
||||
checkArguments("new_ns2ns3ClassB_",nargout,nargin,0);
|
||||
ns2::ns3::ClassB* self = new ns2::ns3::ClassB();
|
||||
out[0] = wrap_constructed(self,"ns2ns3ClassB");
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
% automatically generated by wrap on 2011-Dec-08
|
||||
function result = new_ns2ns3ClassB_(obj)
|
||||
error('need to compile new_ns2ns3ClassB_.cpp');
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
// automatically generated by wrap on 2011-Dec-08
|
||||
#include <wrap/matlab.h>
|
||||
#include <ClassA.h>
|
||||
void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])
|
||||
{
|
||||
checkArguments("ns2ClassA_afunction",nargout,nargin,0);
|
||||
double result = ns2::ClassA::afunction();
|
||||
out[0] = wrap< double >(result);
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
function result = ns2ClassA_afunction()
|
||||
% usage: x = ns2ClassA_afunction()
|
||||
error('need to compile ns2ClassA_afunction.cpp');
|
||||
end
|
|
@ -9,10 +9,6 @@ class Point2 {
|
|||
VectorNotEigen vectorConfusion();
|
||||
};
|
||||
|
||||
namespace ns_outer {
|
||||
|
||||
namespace ns_inner {
|
||||
|
||||
class Point3 {
|
||||
Point3(double x, double y, double z);
|
||||
double norm() const;
|
||||
|
@ -24,9 +20,6 @@ class Point3 {
|
|||
|
||||
// another comment
|
||||
|
||||
// NOTE: you *must* end namespaces as follows:
|
||||
}///\namespace
|
||||
|
||||
// another comment
|
||||
|
||||
/**
|
||||
|
@ -76,8 +69,6 @@ class Test {
|
|||
// even more comments at the end!
|
||||
};
|
||||
|
||||
}///\namespace
|
||||
|
||||
// comments at the end!
|
||||
|
||||
// even more comments at the end!
|
||||
|
|
|
@ -5,33 +5,39 @@
|
|||
namespace ns1 {
|
||||
|
||||
class ClassA {
|
||||
|
||||
ClassA();
|
||||
};
|
||||
|
||||
class ClassB {
|
||||
|
||||
ClassB();
|
||||
};
|
||||
|
||||
}///\namespace
|
||||
}///\namespace ns1
|
||||
|
||||
namespace ns2 {
|
||||
|
||||
class ClassA {
|
||||
ClassA();
|
||||
static double afunction();
|
||||
double memberFunction();
|
||||
};
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
class ClassB {
|
||||
ClassB();
|
||||
};
|
||||
|
||||
}///\namespace
|
||||
}///\namespace ns3
|
||||
|
||||
class ClassC {
|
||||
ClassC();
|
||||
};
|
||||
|
||||
}///\namespace
|
||||
}///\namespace ns2
|
||||
|
||||
class ClassD {
|
||||
ClassD();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -50,6 +50,10 @@ TEST( wrap, check_exception ) {
|
|||
THROWS_EXCEPTION(Module("/notarealpath", "geometry",enable_verbose));
|
||||
CHECK_EXCEPTION(Module("/alsonotarealpath", "geometry",enable_verbose), CantOpenFile);
|
||||
|
||||
// clean out previous generated code
|
||||
string cleanCmd = "rm -rf actual";
|
||||
system(cleanCmd.c_str());
|
||||
|
||||
string path = topdir + "/wrap/tests";
|
||||
Module module(path.c_str(), "testWrap1",enable_verbose);
|
||||
CHECK_EXCEPTION(module.matlab_code("actual", "", "mexa64", "-O5"), DependencyMissing);
|
||||
|
@ -78,9 +82,7 @@ TEST( wrap, parse ) {
|
|||
EXPECT_LONGS_EQUAL(1, cls.constructors.size());
|
||||
EXPECT_LONGS_EQUAL(1, cls.methods.size());
|
||||
EXPECT_LONGS_EQUAL(2, cls.static_methods.size());
|
||||
EXPECT_LONGS_EQUAL(2, cls.namespaces.size());
|
||||
EXPECT(assert_equal("ns_outer", cls.namespaces.front()));
|
||||
EXPECT(assert_equal("ns_inner", cls.namespaces.back()));
|
||||
EXPECT_LONGS_EQUAL(0, cls.namespaces.size());
|
||||
|
||||
// first constructor takes 3 doubles
|
||||
Constructor c1 = cls.constructors.front();
|
||||
|
@ -95,9 +97,9 @@ TEST( wrap, parse ) {
|
|||
|
||||
// check method
|
||||
Method m1 = cls.methods.front();
|
||||
EXPECT(assert_equal("double", m1.returnVal_.type1));
|
||||
EXPECT(assert_equal("norm", m1.name_));
|
||||
EXPECT_LONGS_EQUAL(0, m1.args_.size());
|
||||
EXPECT(assert_equal("double", m1.returnVal.type1));
|
||||
EXPECT(assert_equal("norm", m1.name));
|
||||
EXPECT_LONGS_EQUAL(0, m1.args.size());
|
||||
EXPECT(m1.is_const_);
|
||||
}
|
||||
|
||||
|
@ -108,14 +110,13 @@ TEST( wrap, parse ) {
|
|||
EXPECT_LONGS_EQUAL( 2, testCls.constructors.size());
|
||||
EXPECT_LONGS_EQUAL(19, testCls.methods.size());
|
||||
EXPECT_LONGS_EQUAL( 0, testCls.static_methods.size());
|
||||
EXPECT_LONGS_EQUAL( 1, testCls.namespaces.size());
|
||||
EXPECT(assert_equal("ns_outer", testCls.namespaces.front()));
|
||||
EXPECT_LONGS_EQUAL( 0, testCls.namespaces.size());
|
||||
|
||||
// function to parse: pair<Vector,Matrix> return_pair (Vector v, Matrix A) const;
|
||||
Method m2 = testCls.methods.front();
|
||||
EXPECT(m2.returnVal_.isPair);
|
||||
EXPECT(m2.returnVal_.category1 == ReturnValue::EIGEN);
|
||||
EXPECT(m2.returnVal_.category2 == ReturnValue::EIGEN);
|
||||
EXPECT(m2.returnVal.isPair);
|
||||
EXPECT(m2.returnVal.category1 == ReturnValue::EIGEN);
|
||||
EXPECT(m2.returnVal.category2 == ReturnValue::EIGEN);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,8 +155,26 @@ TEST( wrap, parse_namespaces ) {
|
|||
Class cls6 = module.classes.at(5);
|
||||
EXPECT(assert_equal("ClassD", cls6.name));
|
||||
EXPECT_LONGS_EQUAL(0, cls6.namespaces.size());
|
||||
if (!cls6.namespaces.empty())
|
||||
cout << "Extraneous namespace: " << cls6.namespaces.front() << endl;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
TEST( wrap, matlab_code_namespaces ) {
|
||||
string header_path = topdir + "/wrap/tests";
|
||||
Module module(header_path.c_str(), "testNamespaces",enable_verbose);
|
||||
EXPECT_LONGS_EQUAL(6, module.classes.size());
|
||||
string path = topdir + "/wrap";
|
||||
|
||||
// clean out previous generated code
|
||||
string cleanCmd = "rm -rf actual_namespaces";
|
||||
system(cleanCmd.c_str());
|
||||
|
||||
// emit MATLAB code
|
||||
string exp_path = path + "/tests/expected_namespaces/";
|
||||
string act_path = "actual_namespaces/";
|
||||
module.matlab_code("actual_namespaces", "", "mexa64", "-O5");
|
||||
|
||||
EXPECT(files_equal(exp_path + "make_testNamespaces.m", act_path + "make_testNamespaces.m"));
|
||||
EXPECT(files_equal(exp_path + "Makefile" , act_path + "Makefile" ));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
Loading…
Reference in New Issue