diff --git a/wrap/Class.cpp b/wrap/Class.cpp index cf56f73a1..08ce392a0 100644 --- a/wrap/Class.cpp +++ b/wrap/Class.cpp @@ -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 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; +} + +/* ************************************************************************* */ diff --git a/wrap/Class.h b/wrap/Class.h index f02456f89..5938dc578 100644 --- a/wrap/Class.h +++ b/wrap/Class.h @@ -18,7 +18,6 @@ #pragma once #include -#include #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 constructors; ///< Class constructors - std::list methods; ///< Class methods - std::list static_methods; ///< Static methods + std::vector constructors; ///< Class constructors + std::vector methods; ///< Class methods + std::vector static_methods; ///< Static methods std::vector 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 diff --git a/wrap/Constructor.cpp b/wrap/Constructor.cpp index 346fc45da..c4458e198 100644 --- a/wrap/Constructor.cpp +++ b/wrap/Constructor.cpp @@ -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 " << 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 diff --git a/wrap/Constructor.h b/wrap/Constructor.h index 93f9b145b..7ad8cd9d5 100644 --- a/wrap/Constructor.h +++ b/wrap/Constructor.h @@ -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 diff --git a/wrap/Method.cpp b/wrap/Method.cpp index bf0426c3e..8dbc3cb4f 100644 --- a/wrap/Method.cpp +++ b/wrap/Method.cpp @@ -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 = 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(result); - returnVal_.wrap_result(ofs); + returnVal.wrap_result(ofs); // finish ofs << "}\n"; diff --git a/wrap/Method.h b/wrap/Method.h index 843a2053b..c3a9f1e00 100644 --- a/wrap/Method.h +++ b/wrap/Method.h @@ -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 diff --git a/wrap/Module.cpp b/wrap/Module.cpp index f1b6c4acb..998f1992d 100644 --- a/wrap/Module.cpp +++ b/wrap/Module.cpp @@ -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 +void verifyArguments(const vector& validArgs, const vector& 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(validArgs, cls.constructors); + verifyArguments(validArgs, cls.static_methods); + verifyArguments(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; diff --git a/wrap/StaticMethod.cpp b/wrap/StaticMethod.cpp index 763cb38f4..352c9c680 100644 --- a/wrap/StaticMethod.cpp +++ b/wrap/StaticMethod.cpp @@ -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(result); diff --git a/wrap/StaticMethod.h b/wrap/StaticMethod.h index c58b26fe8..c50959d02 100644 --- a/wrap/StaticMethod.h +++ b/wrap/StaticMethod.h @@ -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 diff --git a/wrap/tests/expected_namespaces/@ClassD/ClassD.m b/wrap/tests/expected_namespaces/@ClassD/ClassD.m new file mode 100644 index 000000000..d6b5b452a --- /dev/null +++ b/wrap/tests/expected_namespaces/@ClassD/ClassD.m @@ -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 diff --git a/wrap/tests/expected_namespaces/@ns1ClassA/ns1ClassA.m b/wrap/tests/expected_namespaces/@ns1ClassA/ns1ClassA.m new file mode 100644 index 000000000..f5de15c80 --- /dev/null +++ b/wrap/tests/expected_namespaces/@ns1ClassA/ns1ClassA.m @@ -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 diff --git a/wrap/tests/expected_namespaces/@ns1ClassB/ns1ClassB.m b/wrap/tests/expected_namespaces/@ns1ClassB/ns1ClassB.m new file mode 100644 index 000000000..189dab25b --- /dev/null +++ b/wrap/tests/expected_namespaces/@ns1ClassB/ns1ClassB.m @@ -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 diff --git a/wrap/tests/expected_namespaces/@ns2ClassA/memberFunction.cpp b/wrap/tests/expected_namespaces/@ns2ClassA/memberFunction.cpp new file mode 100644 index 000000000..d051c74ec --- /dev/null +++ b/wrap/tests/expected_namespaces/@ns2ClassA/memberFunction.cpp @@ -0,0 +1,10 @@ +// automatically generated by wrap on 2011-Dec-08 +#include +#include +void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[]) +{ + checkArguments("memberFunction",nargout,nargin-1,0); + shared_ptr self = unwrap_shared_ptr< ns2::ClassA >(in[0],"ns2ClassA"); + double result = self->memberFunction(); + out[0] = wrap< double >(result); +} diff --git a/wrap/tests/expected_namespaces/@ns2ClassA/memberFunction.m b/wrap/tests/expected_namespaces/@ns2ClassA/memberFunction.m new file mode 100644 index 000000000..8e8d24bd7 --- /dev/null +++ b/wrap/tests/expected_namespaces/@ns2ClassA/memberFunction.m @@ -0,0 +1,4 @@ +function result = memberFunction(obj) +% usage: obj.memberFunction() + error('need to compile memberFunction.cpp'); +end diff --git a/wrap/tests/expected_namespaces/@ns2ClassA/ns2ClassA.m b/wrap/tests/expected_namespaces/@ns2ClassA/ns2ClassA.m new file mode 100644 index 000000000..f0521377e --- /dev/null +++ b/wrap/tests/expected_namespaces/@ns2ClassA/ns2ClassA.m @@ -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 diff --git a/wrap/tests/expected_namespaces/@ns2ClassC/ns2ClassC.m b/wrap/tests/expected_namespaces/@ns2ClassC/ns2ClassC.m new file mode 100644 index 000000000..78fc02073 --- /dev/null +++ b/wrap/tests/expected_namespaces/@ns2ClassC/ns2ClassC.m @@ -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 diff --git a/wrap/tests/expected_namespaces/@ns2ns3ClassB/ns2ns3ClassB.m b/wrap/tests/expected_namespaces/@ns2ns3ClassB/ns2ns3ClassB.m new file mode 100644 index 000000000..35891c5a7 --- /dev/null +++ b/wrap/tests/expected_namespaces/@ns2ns3ClassB/ns2ns3ClassB.m @@ -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 diff --git a/wrap/tests/expected_namespaces/Makefile b/wrap/tests/expected_namespaces/Makefile new file mode 100644 index 000000000..844bf9692 --- /dev/null +++ b/wrap/tests/expected_namespaces/Makefile @@ -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) + + diff --git a/wrap/tests/expected_namespaces/make_testNamespaces.m b/wrap/tests/expected_namespaces/make_testNamespaces.m new file mode 100644 index 000000000..76cb43fbb --- /dev/null +++ b/wrap/tests/expected_namespaces/make_testNamespaces.m @@ -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 diff --git a/wrap/tests/expected_namespaces/new_ClassD_.cpp b/wrap/tests/expected_namespaces/new_ClassD_.cpp new file mode 100644 index 000000000..ec7212786 --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ClassD_.cpp @@ -0,0 +1,9 @@ +// automatically generated by wrap on 2011-Dec-08 +#include +#include +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"); +} diff --git a/wrap/tests/expected_namespaces/new_ClassD_.m b/wrap/tests/expected_namespaces/new_ClassD_.m new file mode 100644 index 000000000..c5f53f130 --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ClassD_.m @@ -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 diff --git a/wrap/tests/expected_namespaces/new_ns1ClassA_.cpp b/wrap/tests/expected_namespaces/new_ns1ClassA_.cpp new file mode 100644 index 000000000..2db8ef767 --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ns1ClassA_.cpp @@ -0,0 +1,9 @@ +// automatically generated by wrap on 2011-Dec-08 +#include +#include +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"); +} diff --git a/wrap/tests/expected_namespaces/new_ns1ClassA_.m b/wrap/tests/expected_namespaces/new_ns1ClassA_.m new file mode 100644 index 000000000..89cd8b0a2 --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ns1ClassA_.m @@ -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 diff --git a/wrap/tests/expected_namespaces/new_ns1ClassB_.cpp b/wrap/tests/expected_namespaces/new_ns1ClassB_.cpp new file mode 100644 index 000000000..b4ac7038a --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ns1ClassB_.cpp @@ -0,0 +1,9 @@ +// automatically generated by wrap on 2011-Dec-08 +#include +#include +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"); +} diff --git a/wrap/tests/expected_namespaces/new_ns1ClassB_.m b/wrap/tests/expected_namespaces/new_ns1ClassB_.m new file mode 100644 index 000000000..5430f85aa --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ns1ClassB_.m @@ -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 diff --git a/wrap/tests/expected_namespaces/new_ns2ClassA_.cpp b/wrap/tests/expected_namespaces/new_ns2ClassA_.cpp new file mode 100644 index 000000000..cc4ec309b --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ns2ClassA_.cpp @@ -0,0 +1,9 @@ +// automatically generated by wrap on 2011-Dec-08 +#include +#include +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"); +} diff --git a/wrap/tests/expected_namespaces/new_ns2ClassA_.m b/wrap/tests/expected_namespaces/new_ns2ClassA_.m new file mode 100644 index 000000000..bb8b2a24a --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ns2ClassA_.m @@ -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 diff --git a/wrap/tests/expected_namespaces/new_ns2ClassC_.cpp b/wrap/tests/expected_namespaces/new_ns2ClassC_.cpp new file mode 100644 index 000000000..b43a7cd6b --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ns2ClassC_.cpp @@ -0,0 +1,9 @@ +// automatically generated by wrap on 2011-Dec-08 +#include +#include +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"); +} diff --git a/wrap/tests/expected_namespaces/new_ns2ClassC_.m b/wrap/tests/expected_namespaces/new_ns2ClassC_.m new file mode 100644 index 000000000..91e643c4b --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ns2ClassC_.m @@ -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 diff --git a/wrap/tests/expected_namespaces/new_ns2ns3ClassB_.cpp b/wrap/tests/expected_namespaces/new_ns2ns3ClassB_.cpp new file mode 100644 index 000000000..3916ed3ff --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ns2ns3ClassB_.cpp @@ -0,0 +1,9 @@ +// automatically generated by wrap on 2011-Dec-08 +#include +#include +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"); +} diff --git a/wrap/tests/expected_namespaces/new_ns2ns3ClassB_.m b/wrap/tests/expected_namespaces/new_ns2ns3ClassB_.m new file mode 100644 index 000000000..54b38a16c --- /dev/null +++ b/wrap/tests/expected_namespaces/new_ns2ns3ClassB_.m @@ -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 diff --git a/wrap/tests/expected_namespaces/ns2ClassA_afunction.cpp b/wrap/tests/expected_namespaces/ns2ClassA_afunction.cpp new file mode 100644 index 000000000..dff68090a --- /dev/null +++ b/wrap/tests/expected_namespaces/ns2ClassA_afunction.cpp @@ -0,0 +1,9 @@ +// automatically generated by wrap on 2011-Dec-08 +#include +#include +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); +} diff --git a/wrap/tests/expected_namespaces/ns2ClassA_afunction.m b/wrap/tests/expected_namespaces/ns2ClassA_afunction.m new file mode 100644 index 000000000..0482d1548 --- /dev/null +++ b/wrap/tests/expected_namespaces/ns2ClassA_afunction.m @@ -0,0 +1,4 @@ +function result = ns2ClassA_afunction() +% usage: x = ns2ClassA_afunction() + error('need to compile ns2ClassA_afunction.cpp'); +end diff --git a/wrap/tests/geometry.h b/wrap/tests/geometry.h index b8427faa3..2eac86bfe 100644 --- a/wrap/tests/geometry.h +++ b/wrap/tests/geometry.h @@ -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! diff --git a/wrap/tests/testNamespaces.h b/wrap/tests/testNamespaces.h index f95e08a74..5b46f99ac 100644 --- a/wrap/tests/testNamespaces.h +++ b/wrap/tests/testNamespaces.h @@ -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(); }; diff --git a/wrap/tests/testWrap.cpp b/wrap/tests/testWrap.cpp index 7b60e9ad2..f9151dba2 100644 --- a/wrap/tests/testWrap.cpp +++ b/wrap/tests/testWrap.cpp @@ -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 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" )); } /* ************************************************************************* */