Unified file writing to use a custom class to allow for smart checking

release/4.3a0
Alex Cunningham 2012-01-15 21:42:41 +00:00
parent ea1ef1fa85
commit 66a9d635b3
16 changed files with 299 additions and 201 deletions

View File

@ -34,29 +34,29 @@ string Argument::matlabClass() const {
} }
/* ************************************************************************* */ /* ************************************************************************* */
void Argument::matlab_unwrap(ofstream& ofs, const string& matlabName) const { void Argument::matlab_unwrap(FileWriter& file, const string& matlabName) const {
ofs << " "; file.oss << " ";
string cppType = qualifiedType("::"); string cppType = qualifiedType("::");
string matlabType = qualifiedType(); string matlabType = qualifiedType();
if (is_ptr) if (is_ptr)
// A pointer: emit an "unwrap_shared_ptr" call which returns a pointer // A pointer: emit an "unwrap_shared_ptr" call which returns a pointer
ofs << "shared_ptr<" << cppType << "> " << name << " = unwrap_shared_ptr< "; file.oss << "shared_ptr<" << cppType << "> " << name << " = unwrap_shared_ptr< ";
else if (is_ref) else if (is_ref)
// A reference: emit an "unwrap_shared_ptr" call and de-reference the pointer // A reference: emit an "unwrap_shared_ptr" call and de-reference the pointer
ofs << cppType << "& " << name << " = *unwrap_shared_ptr< "; file.oss << cppType << "& " << name << " = *unwrap_shared_ptr< ";
else else
// Not a pointer or a reference: emit an "unwrap" call // Not a pointer or a reference: emit an "unwrap" call
// unwrap is specified in matlab.h as a series of template specializations // unwrap is specified in matlab.h as a series of template specializations
// that know how to unpack the expected MATLAB object // that know how to unpack the expected MATLAB object
// example: double tol = unwrap< double >(in[2]); // example: double tol = unwrap< double >(in[2]);
// example: Vector v = unwrap< Vector >(in[1]); // example: Vector v = unwrap< Vector >(in[1]);
ofs << cppType << " " << name << " = unwrap< "; file.oss << cppType << " " << name << " = unwrap< ";
ofs << cppType << " >(" << matlabName; file.oss << cppType << " >(" << matlabName;
if (is_ptr || is_ref) ofs << ", \"" << matlabType << "\""; if (is_ptr || is_ref) file.oss << ", \"" << matlabType << "\"";
ofs << ");" << endl; file.oss << ");" << endl;
} }
/* ************************************************************************* */ /* ************************************************************************* */
@ -107,12 +107,12 @@ string ArgumentList::names() const {
} }
/* ************************************************************************* */ /* ************************************************************************* */
void ArgumentList::matlab_unwrap(ofstream& ofs, int start) const { void ArgumentList::matlab_unwrap(FileWriter& file, int start) const {
int index = start; int index = start;
BOOST_FOREACH(Argument arg, *this) { BOOST_FOREACH(Argument arg, *this) {
stringstream buf; stringstream buf;
buf << "in[" << index << "]"; buf << "in[" << index << "]";
arg.matlab_unwrap(ofs,buf.str()); arg.matlab_unwrap(file,buf.str());
index++; index++;
} }
} }

View File

@ -20,6 +20,8 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "FileWriter.h"
namespace wrap { namespace wrap {
/// Argument class /// Argument class
@ -40,7 +42,7 @@ struct Argument {
std::string qualifiedType(const std::string& delim = "") const; std::string qualifiedType(const std::string& delim = "") const;
/// MATLAB code generation, MATLAB to C++ /// MATLAB code generation, MATLAB to C++
void matlab_unwrap(std::ofstream& ofs, const std::string& matlabName) const; void matlab_unwrap(FileWriter& file, const std::string& matlabName) const;
}; };
/// Argument list is just a container with Arguments /// Argument list is just a container with Arguments
@ -59,10 +61,10 @@ struct ArgumentList: public std::vector<Argument> {
/** /**
* emit code to unwrap arguments * emit code to unwrap arguments
* @param ofs output stream * @param file output stream
* @param start initial index for input array, set to 1 for method * @param start initial index for input array, set to 1 for method
*/ */
void matlab_unwrap(std::ofstream& ofs, int start = 0) const; // MATLAB to C++ void matlab_unwrap(FileWriter& file, int start = 0) const; // MATLAB to C++
}; };
} // \namespace wrap } // \namespace wrap

View File

@ -29,31 +29,31 @@ using namespace wrap;
/* ************************************************************************* */ /* ************************************************************************* */
void Class::matlab_proxy(const string& classFile) const { void Class::matlab_proxy(const string& classFile) const {
// open destination classFile // open destination classFile
ofstream ofs(classFile.c_str()); FileWriter file(classFile, "%");
if(!ofs) throw CantOpenFile(classFile); // if(!file) throw CantOpenFile(classFile);
if(verbose_) cerr << "generating " << classFile << endl; if(verbose_) cerr << "generating " << classFile << endl;
// get the name of actual matlab object // get the name of actual matlab object
string matlabName = qualifiedName(); string matlabName = qualifiedName();
// emit class proxy code // emit class proxy code
ofs << "classdef " << matlabName << endl; file.oss << "classdef " << matlabName << endl;
ofs << " properties" << endl; file.oss << " properties" << endl;
ofs << " self = 0" << endl; file.oss << " self = 0" << endl;
ofs << " end" << endl; file.oss << " end" << endl;
ofs << " methods" << endl; file.oss << " methods" << endl;
ofs << " function obj = " << matlabName << "(varargin)" << endl; file.oss << " function obj = " << matlabName << "(varargin)" << endl;
BOOST_FOREACH(Constructor c, constructors) BOOST_FOREACH(Constructor c, constructors)
c.matlab_proxy_fragment(ofs,matlabName); c.matlab_proxy_fragment(file,matlabName);
ofs << " if nargin ~= 13 && obj.self == 0, error('" << matlabName << " constructor failed'); end" << endl; file.oss << " if nargin ~= 13 && obj.self == 0, error('" << matlabName << " constructor failed'); end" << endl;
ofs << " end" << endl; file.oss << " end" << endl;
ofs << " function display(obj), obj.print(''); end" << endl; file.oss << " function display(obj), obj.print(''); end" << endl;
ofs << " function disp(obj), obj.display; end" << endl; file.oss << " function disp(obj), obj.display; end" << endl;
ofs << " end" << endl; file.oss << " end" << endl;
ofs << "end" << endl; file.oss << "end" << endl;
// close file // close file
ofs.close(); file.emit(false);
} }
/* ************************************************************************* */ /* ************************************************************************* */
@ -83,23 +83,23 @@ void Class::matlab_static_methods(const string& toolboxPath, const vector<string
} }
/* ************************************************************************* */ /* ************************************************************************* */
void Class::matlab_make_fragment(ofstream& ofs, void Class::matlab_make_fragment(FileWriter& file,
const string& toolboxPath, const string& toolboxPath,
const string& mexFlags) const { const string& mexFlags) const {
string mex = "mex " + mexFlags + " "; string mex = "mex " + mexFlags + " ";
string matlabClassName = qualifiedName(); string matlabClassName = qualifiedName();
BOOST_FOREACH(Constructor c, constructors) BOOST_FOREACH(Constructor c, constructors)
ofs << mex << c.matlab_wrapper_name(matlabClassName) << ".cpp" << endl; file.oss << mex << c.matlab_wrapper_name(matlabClassName) << ".cpp" << endl;
BOOST_FOREACH(StaticMethod sm, static_methods) BOOST_FOREACH(StaticMethod sm, static_methods)
ofs << mex << matlabClassName + "_" + sm.name << ".cpp" << endl; file.oss << mex << matlabClassName + "_" + sm.name << ".cpp" << endl;
ofs << endl << "cd @" << matlabClassName << endl; file.oss << endl << "cd @" << matlabClassName << endl;
BOOST_FOREACH(Method m, methods) BOOST_FOREACH(Method m, methods)
ofs << mex << m.name << ".cpp" << endl; file.oss << mex << m.name << ".cpp" << endl;
ofs << endl; file.oss << endl;
} }
/* ************************************************************************* */ /* ************************************************************************* */
void Class::makefile_fragment(ofstream& ofs) const { void Class::makefile_fragment(FileWriter& file) const {
// new_Point2_.$(MEXENDING): new_Point2_.cpp // new_Point2_.$(MEXENDING): new_Point2_.cpp
// $(MEX) $(mex_flags) new_Point2_.cpp // $(MEX) $(mex_flags) new_Point2_.cpp
// new_Point2_dd.$(MEXENDING): new_Point2_dd.cpp // new_Point2_dd.$(MEXENDING): new_Point2_dd.cpp
@ -131,16 +131,16 @@ void Class::makefile_fragment(ofstream& ofs) const {
} }
BOOST_FOREACH(const string& file_base, file_names) { BOOST_FOREACH(const string& file_base, file_names) {
ofs << file_base << ".$(MEXENDING): " << file_base << ".cpp" << endl; file.oss << file_base << ".$(MEXENDING): " << file_base << ".cpp" << endl;
ofs << "\t$(MEX) $(mex_flags) " << file_base << ".cpp -output " << file_base << endl; file.oss << "\t$(MEX) $(mex_flags) " << file_base << ".cpp -output " << file_base << endl;
} }
// class target // class target
ofs << "\n" << matlabName << ": "; file.oss << "\n" << matlabName << ": ";
BOOST_FOREACH(const string& file_base, file_names) { BOOST_FOREACH(const string& file_base, file_names) {
ofs << file_base << ".$(MEXENDING) "; file.oss << file_base << ".$(MEXENDING) ";
} }
ofs << "\n" << endl; file.oss << "\n" << endl;
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -47,10 +47,10 @@ struct Class {
const std::vector<std::string>& using_namespaces) const; ///< emit method wrappers const std::vector<std::string>& using_namespaces) const; ///< emit method wrappers
void matlab_static_methods(const std::string& classPath, void matlab_static_methods(const std::string& classPath,
const std::vector<std::string>& using_namespaces) const; ///< emit static method wrappers const std::vector<std::string>& using_namespaces) const; ///< emit static method wrappers
void matlab_make_fragment(std::ofstream& ofs, void matlab_make_fragment(FileWriter& file,
const std::string& toolboxPath, const std::string& toolboxPath,
const std::string& mexFlags) const; ///< emit make fragment for global make script const std::string& mexFlags) const; ///< emit make fragment for global make script
void makefile_fragment(std::ofstream& ofs) const; ///< emit makefile fragment void makefile_fragment(FileWriter& file) const; ///< emit makefile fragment
std::string qualifiedName(const std::string& delim = "") const; ///< creates a namespace-qualified name, optional delimiter std::string qualifiedName(const std::string& delim = "") const; ///< creates a namespace-qualified name, optional delimiter
}; };

View File

@ -32,28 +32,28 @@ string Constructor::matlab_wrapper_name(const string& className) const {
} }
/* ************************************************************************* */ /* ************************************************************************* */
void Constructor::matlab_proxy_fragment(ofstream& ofs, const string& className) const { void Constructor::matlab_proxy_fragment(FileWriter& file, const string& className) const {
size_t nrArgs = args.size(); size_t nrArgs = args.size();
// check for number of arguments... // check for number of arguments...
ofs << " if (nargin == " << nrArgs; file.oss << " if (nargin == " << nrArgs;
if (nrArgs>0) ofs << " && "; if (nrArgs>0) file.oss << " && ";
// ...and their types // ...and their types
bool first = true; bool first = true;
for(size_t i=0;i<nrArgs;i++) { for(size_t i=0;i<nrArgs;i++) {
if (!first) ofs << " && "; if (!first) file.oss << " && ";
ofs << "isa(varargin{" << i+1 << "},'" << args[i].matlabClass() << "')"; file.oss << "isa(varargin{" << i+1 << "},'" << args[i].matlabClass() << "')";
first=false; first=false;
} }
// emit code for calling constructor // emit code for calling constructor
ofs << "), obj.self = " << matlab_wrapper_name(className) << "("; file.oss << "), obj.self = " << matlab_wrapper_name(className) << "(";
// emit constructor arguments // emit constructor arguments
first = true; first = true;
for(size_t i=0;i<nrArgs;i++) { for(size_t i=0;i<nrArgs;i++) {
if (!first) ofs << ","; if (!first) file.oss << ",";
ofs << "varargin{" << i+1 << "}"; file.oss << "varargin{" << i+1 << "}";
first=false; first=false;
} }
ofs << "); end" << endl; file.oss << "); end" << endl;
} }
/* ************************************************************************* */ /* ************************************************************************* */
@ -63,20 +63,20 @@ void Constructor::matlab_mfile(const string& toolboxPath, const string& qualifie
// open destination m-file // open destination m-file
string wrapperFile = toolboxPath + "/" + matlabName + ".m"; string wrapperFile = toolboxPath + "/" + matlabName + ".m";
ofstream ofs(wrapperFile.c_str()); FileWriter file(wrapperFile, "%");
if(!ofs) throw CantOpenFile(wrapperFile); // if(!file) throw CantOpenFile(wrapperFile);
if(verbose_) cerr << "generating " << wrapperFile << endl; if(verbose_) cerr << "generating " << wrapperFile << endl;
// generate code // generate code
generateHeaderComment(ofs, "%"); // generateHeaderComment(file, "%");
ofs << "function result = " << matlabName << "(obj"; file.oss << "function result = " << matlabName << "(obj";
if (args.size()) ofs << "," << args.names(); if (args.size()) file.oss << "," << args.names();
ofs << ")" << endl; file.oss << ")" << endl;
ofs << " error('need to compile " << matlabName << ".cpp');" << endl; file.oss << " error('need to compile " << matlabName << ".cpp');" << endl;
ofs << "end" << endl; file.oss << "end" << endl;
// close file // close file
ofs.close(); file.emit(true);
} }
/* ************************************************************************* */ /* ************************************************************************* */
@ -88,25 +88,25 @@ void Constructor::matlab_wrapper(const string& toolboxPath,
// open destination wrapperFile // open destination wrapperFile
string wrapperFile = toolboxPath + "/" + matlabName + ".cpp"; string wrapperFile = toolboxPath + "/" + matlabName + ".cpp";
ofstream ofs(wrapperFile.c_str()); FileWriter file(wrapperFile, "//");
if(!ofs) throw CantOpenFile(wrapperFile); // if(!file) throw CantOpenFile(wrapperFile);
if(verbose_) cerr << "generating " << wrapperFile << endl; if(verbose_) cerr << "generating " << wrapperFile << endl;
// generate code // generate code
generateHeaderComment(ofs, "//"); // generateHeaderComment(file, "//");
generateIncludes(ofs, name, includes); generateIncludes(file, name, includes);
generateUsingNamespace(ofs, using_namespaces); generateUsingNamespace(file, using_namespaces);
ofs << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl; file.oss << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl;
ofs << "{" << endl; file.oss << "{" << endl;
ofs << " checkArguments(\"" << matlabName << "\",nargout,nargin," << args.size() << ");" << endl; file.oss << " checkArguments(\"" << matlabName << "\",nargout,nargin," << args.size() << ");" << endl;
args.matlab_unwrap(ofs); // unwrap arguments args.matlab_unwrap(file); // unwrap arguments
ofs << " " << cppClassName << "* self = new " << cppClassName << "(" << args.names() << ");" << endl; // need qualified name, delim: "::" file.oss << " " << cppClassName << "* self = new " << cppClassName << "(" << args.names() << ");" << endl; // need qualified name, delim: "::"
ofs << " out[0] = wrap_constructed(self,\"" << matlabClassName << "\");" << endl; // need matlab qualified name file.oss << " out[0] = wrap_constructed(self,\"" << matlabClassName << "\");" << endl; // need matlab qualified name
ofs << "}" << endl; file.oss << "}" << endl;
// close file // close file
ofs.close(); file.emit(true);
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -48,7 +48,7 @@ struct Constructor {
* Create fragment to select constructor in proxy class, e.g., * Create fragment to select constructor in proxy class, e.g.,
* if nargin == 2, obj.self = new_Pose3_RP(varargin{1},varargin{2}); end * if nargin == 2, obj.self = new_Pose3_RP(varargin{1},varargin{2}); end
*/ */
void matlab_proxy_fragment(std::ofstream& ofs, const std::string& className) const; void matlab_proxy_fragment(FileWriter& file, const std::string& className) const;
/// m-file /// m-file
void matlab_mfile(const std::string& toolboxPath, void matlab_mfile(const std::string& toolboxPath,

56
wrap/FileWriter.cpp Normal file
View File

@ -0,0 +1,56 @@
/**
* @file FileWriter.cpp
*
* @date Jan 15, 2012
* @author Alex Cunningham
*/
#include "FileWriter.h"
#include "utilities.h"
#include <boost/date_time/gregorian/gregorian.hpp>
#include <fstream>
using namespace std;
using namespace boost::gregorian;
using namespace wrap;
/* ************************************************************************* */
FileWriter::FileWriter(const string& filename, const string& comment_str)
: filename_(filename), comment_str_(comment_str)
{
}
/* ************************************************************************* */
void FileWriter::emit(bool add_header, bool force) const {
// Standard write - just overwrite for verification
ofstream ofs(filename_.c_str());
if (!ofs) throw CantOpenFile(filename_);
// header
if (add_header) {
date today = day_clock::local_day();
ofs << comment_str_ << " automatically generated by wrap on " << today << endl;
}
// dump in stringstream
ofs << oss.str();
ofs.close();
// TODO: add the following checks
// check for existing file
// if exists and we are not forcing writing, read and compare
// if different, write the file with contents of this stream
// add header
}
/* ************************************************************************* */

34
wrap/FileWriter.h Normal file
View File

@ -0,0 +1,34 @@
/**
* @file FileWriter.h
*
* @brief Wrapper for writing files and avoiding overwriting existing files
* This class wraps a stream object and will check that the file is
* actually different to write the new generated file.
*
* @date Jan 15, 2012
* @author Alex Cunningham
*/
#pragma once
#include <sstream>
namespace wrap {
class FileWriter {
protected:
std::string filename_;
std::string comment_str_;
public:
std::ostringstream oss; ///< Primary stream for operating on the file
/** Create a writer with a filename and delimiter for the header comment */
FileWriter(const std::string& filename, const std::string& comment_str="");
/** Writes the contents of the stringstream to the file, checking if actually new */
void emit(bool add_header, bool force=false) const;
};
} // \namespace wrap

View File

@ -19,7 +19,7 @@ if ENABLE_BUILD_TOOLBOX
# Build a library from the core sources # Build a library from the core sources
sources += utilities.cpp Argument.cpp ReturnValue.cpp Constructor.cpp sources += utilities.cpp Argument.cpp ReturnValue.cpp Constructor.cpp
sources += Method.cpp StaticMethod.cpp Class.cpp Module.cpp sources += Method.cpp StaticMethod.cpp Class.cpp Module.cpp FileWriter.cpp
check_PROGRAMS += tests/testSpirit tests/testWrap check_PROGRAMS += tests/testSpirit tests/testWrap
if ENABLE_INSTALL_WRAP if ENABLE_INSTALL_WRAP
wrap_PROGRAMS += wrap wrap_PROGRAMS += wrap

View File

@ -30,21 +30,21 @@ void Method::matlab_mfile(const string& classPath) const {
// open destination m-file // open destination m-file
string wrapperFile = classPath + "/" + name + ".m"; string wrapperFile = classPath + "/" + name + ".m";
ofstream ofs(wrapperFile.c_str()); FileWriter file(wrapperFile.c_str(), "%");
if(!ofs) throw CantOpenFile(wrapperFile); // if(!file) throw CantOpenFile(wrapperFile);
if(verbose_) cerr << "generating " << wrapperFile << endl; if(verbose_) cerr << "generating " << wrapperFile << endl;
// generate code // generate code
string returnType = returnVal.matlab_returnType(); string returnType = returnVal.matlab_returnType();
ofs << "function " << returnType << " = " << name << "(obj"; file.oss << "function " << returnType << " = " << name << "(obj";
if (args.size()) ofs << "," << args.names(); if (args.size()) file.oss << "," << args.names();
ofs << ")" << endl; file.oss << ")" << endl;
ofs << "% usage: obj." << name << "(" << args.names() << ")" << endl; file.oss << "% usage: obj." << name << "(" << args.names() << ")" << endl;
ofs << " error('need to compile " << name << ".cpp');" << endl; file.oss << " error('need to compile " << name << ".cpp');" << endl;
ofs << "end" << endl; file.oss << "end" << endl;
// close file // close file
ofs.close(); file.emit(false);
} }
/* ************************************************************************* */ /* ************************************************************************* */
@ -55,51 +55,51 @@ void Method::matlab_wrapper(const string& classPath,
const vector<string>& using_namespaces, const std::vector<std::string>& includes) const { const vector<string>& using_namespaces, const std::vector<std::string>& includes) const {
// open destination wrapperFile // open destination wrapperFile
string wrapperFile = classPath + "/" + name + ".cpp"; string wrapperFile = classPath + "/" + name + ".cpp";
ofstream ofs(wrapperFile.c_str()); FileWriter file(wrapperFile.c_str(), "//");
if(!ofs) throw CantOpenFile(wrapperFile); // if(!file) throw CantOpenFile(wrapperFile);
if(verbose_) cerr << "generating " << wrapperFile << endl; if(verbose_) cerr << "generating " << wrapperFile << endl;
// generate code // generate code
// header // header
generateHeaderComment(ofs, "//"); // generateHeaderComment(file, "//");
generateIncludes(ofs, className, includes); generateIncludes(file, className, includes);
generateUsingNamespace(ofs, using_namespaces); generateUsingNamespace(file, using_namespaces);
// call // call
ofs << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n"; file.oss << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n";
// start // start
ofs << "{\n"; file.oss << "{\n";
// check arguments // check arguments
// extra argument obj -> nargin-1 is passed ! // extra argument obj -> nargin-1 is passed !
// example: checkArguments("equals",nargout,nargin-1,2); // example: checkArguments("equals",nargout,nargin-1,2);
ofs << " checkArguments(\"" << name << "\",nargout,nargin-1," << args.size() << ");\n"; file.oss << " checkArguments(\"" << name << "\",nargout,nargin-1," << args.size() << ");\n";
// get class pointer // get class pointer
// example: shared_ptr<Test> = unwrap_shared_ptr< Test >(in[0], "Test"); // example: shared_ptr<Test> = unwrap_shared_ptr< Test >(in[0], "Test");
ofs << " shared_ptr<" << cppClassName << "> self = unwrap_shared_ptr< " << cppClassName file.oss << " shared_ptr<" << cppClassName << "> self = unwrap_shared_ptr< " << cppClassName
<< " >(in[0],\"" << matlabClassName << "\");" << endl; << " >(in[0],\"" << matlabClassName << "\");" << endl;
// unwrap arguments, see Argument.cpp // unwrap arguments, see Argument.cpp
args.matlab_unwrap(ofs,1); args.matlab_unwrap(file,1);
// call method // call method
// example: bool result = self->return_field(t); // example: bool result = self->return_field(t);
ofs << " "; file.oss << " ";
if (returnVal.type1!="void") if (returnVal.type1!="void")
ofs << returnVal.return_type(true,ReturnValue::pair) << " result = "; file.oss << returnVal.return_type(true,ReturnValue::pair) << " result = ";
ofs << "self->" << name << "(" << args.names() << ");\n"; file.oss << "self->" << name << "(" << args.names() << ");\n";
// wrap result // wrap result
// example: out[0]=wrap<bool>(result); // example: out[0]=wrap<bool>(result);
returnVal.wrap_result(ofs); returnVal.wrap_result(file);
// finish // finish
ofs << "}\n"; file.oss << "}\n";
// close file // close file
ofs.close(); file.emit(true);
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -15,6 +15,7 @@
**/ **/
#include "Module.h" #include "Module.h"
#include "FileWriter.h"
#include "utilities.h" #include "utilities.h"
#include "spirit_actors.h" #include "spirit_actors.h"
@ -24,7 +25,7 @@
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <iostream> #include <iostream>
#include <fstream> //#include <fstream>
using namespace std; using namespace std;
using namespace wrap; using namespace wrap;
@ -279,29 +280,31 @@ void Module::matlab_code(const string& toolboxPath,
system(installCmd.c_str()); system(installCmd.c_str());
// create make m-file // create make m-file
string matlabMakeFile = toolboxPath + "/make_" + name + ".m"; string matlabMakeFileName = toolboxPath + "/make_" + name + ".m";
ofstream ofs(matlabMakeFile.c_str()); FileWriter makeModuleMfile(matlabMakeFileName, "%");
if(!ofs) throw CantOpenFile(matlabMakeFile); // filetream makeModuleMfile(matlabMakeFileName.c_str());
// if(!makeModuleMfile) throw CantOpenFile(matlabMakeFileName);
// create the (actual) make file // create the (actual) make file
string makeFile = toolboxPath + "/Makefile"; string makeFileName = toolboxPath + "/Makefile";
ofstream make_ofs(makeFile.c_str()); FileWriter makeModuleMakefile(makeFileName, "#");
if(!make_ofs) throw CantOpenFile(makeFile); // filetream makeModuleMakefile(makeFileName.c_str());
// if(!makeModuleMakefile) throw CantOpenFile(makeFileName);
if (verbose) cerr << "generating " << matlabMakeFile << endl; if (verbose) cerr << "generating " << matlabMakeFileName << endl;
generateHeaderComment(ofs,"%"); // generateHeaderComment(makeModuleMfile,"%"); // In FileWriter constructor
ofs << "echo on" << endl << endl; makeModuleMfile.oss << "echo on" << endl << endl;
ofs << "toolboxpath = mfilename('fullpath');" << endl; makeModuleMfile.oss << "toolboxpath = mfilename('fullpath');" << endl;
ofs << "delims = find(toolboxpath == '/');" << endl; makeModuleMfile.oss << "delims = find(toolboxpath == '/');" << endl;
ofs << "toolboxpath = toolboxpath(1:(delims(end)-1));" << endl; makeModuleMfile.oss << "toolboxpath = toolboxpath(1:(delims(end)-1));" << endl;
ofs << "clear delims" << endl; makeModuleMfile.oss << "clear delims" << endl;
ofs << "addpath(toolboxpath);" << endl << endl; makeModuleMfile.oss << "addpath(toolboxpath);" << endl << endl;
if (verbose) cerr << "generating " << makeFile << endl; if (verbose) cerr << "generating " << makeFileName << endl;
generateHeaderComment(make_ofs,"#"); // generateHeaderComment(makeModuleMakefile,"#"); // In FileWriter constructor
make_ofs << "\nMEX = mex\n"; makeModuleMakefile.oss << "\nMEX = mex\n";
make_ofs << "MEXENDING = " << mexExt << "\n"; makeModuleMakefile.oss << "MEXENDING = " << mexExt << "\n";
make_ofs << "mex_flags = " << mexFlags << "\n\n"; makeModuleMakefile.oss << "mex_flags = " << mexFlags << "\n\n";
// Dependency check list // Dependency check list
vector<string> validTypes = forward_declarations; vector<string> validTypes = forward_declarations;
@ -315,13 +318,13 @@ void Module::matlab_code(const string& toolboxPath,
validTypes.push_back("Matrix"); validTypes.push_back("Matrix");
// add 'all' to Makefile // add 'all' to Makefile
make_ofs << "all: "; makeModuleMakefile.oss << "all: ";
BOOST_FOREACH(Class cls, classes) { BOOST_FOREACH(Class cls, classes) {
make_ofs << cls.qualifiedName() << " "; makeModuleMakefile.oss << cls.qualifiedName() << " ";
//Create a list of parsed classes for dependency checking //Create a list of parsed classes for dependency checking
validTypes.push_back(cls.qualifiedName("::")); validTypes.push_back(cls.qualifiedName("::"));
} }
make_ofs << "\n\n"; makeModuleMakefile.oss << "\n\n";
// generate proxy classes and wrappers // generate proxy classes and wrappers
BOOST_FOREACH(Class cls, classes) { BOOST_FOREACH(Class cls, classes) {
@ -349,29 +352,31 @@ void Module::matlab_code(const string& toolboxPath,
cls.matlab_methods(classPath,using_namespaces); cls.matlab_methods(classPath,using_namespaces);
// add lines to make m-file // add lines to make m-file
ofs << "%% " << cls.qualifiedName() << endl; makeModuleMfile.oss << "%% " << cls.qualifiedName() << endl;
ofs << "cd(toolboxpath)" << endl; makeModuleMfile.oss << "cd(toolboxpath)" << endl;
cls.matlab_make_fragment(ofs, toolboxPath, mexFlags); cls.matlab_make_fragment(makeModuleMfile, toolboxPath, mexFlags);
// add section to the (actual) make file // add section to the (actual) make file
make_ofs << "# " << cls.qualifiedName() << endl; makeModuleMakefile.oss << "# " << cls.qualifiedName() << endl;
cls.makefile_fragment(make_ofs); cls.makefile_fragment(makeModuleMakefile);
} }
// finish make m-file // finish make m-file
ofs << "cd(toolboxpath)" << endl << endl; makeModuleMfile.oss << "cd(toolboxpath)" << endl << endl;
ofs << "echo off" << endl; makeModuleMfile.oss << "echo off" << endl;
ofs.close(); makeModuleMfile.emit(true); // By default, compare existing file first
// makeModuleMfile.emit();
// make clean at end of Makefile // make clean at end of Makefile
make_ofs << "\n\nclean: \n"; makeModuleMakefile.oss << "\n\nclean: \n";
make_ofs << "\trm -rf *.$(MEXENDING)\n"; makeModuleMakefile.oss << "\trm -rf *.$(MEXENDING)\n";
BOOST_FOREACH(Class cls, classes) BOOST_FOREACH(Class cls, classes)
make_ofs << "\trm -rf @" << cls.qualifiedName() << "/*.$(MEXENDING)\n"; makeModuleMakefile.oss << "\trm -rf @" << cls.qualifiedName() << "/*.$(MEXENDING)\n";
// finish Makefile // finish Makefile
make_ofs << "\n" << endl; makeModuleMakefile.oss << "\n" << endl;
make_ofs.close(); makeModuleMakefile.emit(true);
// makeModuleMakefile.emit();
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -44,33 +44,33 @@ string ReturnValue::qualifiedType2(const string& delim) const {
} }
/* ************************************************************************* */ /* ************************************************************************* */
void ReturnValue::wrap_result(ostream& ofs) const { void ReturnValue::wrap_result(FileWriter& file) const {
string cppType1 = qualifiedType1("::"), matlabType1 = qualifiedType1(); string cppType1 = qualifiedType1("::"), matlabType1 = qualifiedType1();
string cppType2 = qualifiedType2("::"), matlabType2 = qualifiedType2(); string cppType2 = qualifiedType2("::"), matlabType2 = qualifiedType2();
if (isPair) { if (isPair) {
// first return value in pair // first return value in pair
if (isPtr1) // if we already have a pointer if (isPtr1) // if we already have a pointer
ofs << " out[0] = wrap_shared_ptr(result.first,\"" << matlabType1 << "\");\n"; file.oss << " out[0] = wrap_shared_ptr(result.first,\"" << matlabType1 << "\");\n";
else if (category1 == ReturnValue::CLASS) // if we are going to make one else if (category1 == ReturnValue::CLASS) // if we are going to make one
ofs << " out[0] = wrap_shared_ptr(make_shared< " << cppType1 << " >(result.first),\"" << matlabType1 << "\");\n"; file.oss << " out[0] = wrap_shared_ptr(make_shared< " << cppType1 << " >(result.first),\"" << matlabType1 << "\");\n";
else // if basis type else // if basis type
ofs << " out[0] = wrap< " << return_type(true,arg1) << " >(result.first);\n"; file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(result.first);\n";
// second return value in pair // second return value in pair
if (isPtr2) // if we already have a pointer if (isPtr2) // if we already have a pointer
ofs << " out[1] = wrap_shared_ptr(result.second,\"" << type2 << "\");\n"; file.oss << " out[1] = wrap_shared_ptr(result.second,\"" << type2 << "\");\n";
else if (category2 == ReturnValue::CLASS) // if we are going to make one else if (category2 == ReturnValue::CLASS) // if we are going to make one
ofs << " out[1] = wrap_shared_ptr(make_shared< " << cppType2 << " >(result.second),\"" << matlabType2 << "\");\n"; file.oss << " out[1] = wrap_shared_ptr(make_shared< " << cppType2 << " >(result.second),\"" << matlabType2 << "\");\n";
else else
ofs << " out[1] = wrap< " << return_type(true,arg2) << " >(result.second);\n"; file.oss << " out[1] = wrap< " << return_type(true,arg2) << " >(result.second);\n";
} }
else if (isPtr1) else if (isPtr1)
ofs << " out[0] = wrap_shared_ptr(result,\"" << type1 << "\");\n"; file.oss << " out[0] = wrap_shared_ptr(result,\"" << type1 << "\");\n";
else if (category1 == ReturnValue::CLASS) else if (category1 == ReturnValue::CLASS)
ofs << " out[0] = wrap_shared_ptr(make_shared< " << cppType1 << " >(result),\"" << matlabType1 << "\");\n"; file.oss << " out[0] = wrap_shared_ptr(make_shared< " << cppType1 << " >(result),\"" << matlabType1 << "\");\n";
else if (type1!="void") else if (type1!="void")
ofs << " out[0] = wrap< " << return_type(true,arg1) << " >(result);\n"; file.oss << " out[0] = wrap< " << return_type(true,arg1) << " >(result);\n";
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -8,7 +8,8 @@
*/ */
#include <vector> #include <vector>
#include <ostream>
#include "FileWriter.h"
#pragma once #pragma once
@ -46,7 +47,7 @@ struct ReturnValue {
std::string matlab_returnType() const; std::string matlab_returnType() const;
void wrap_result(std::ostream& ofs) const; void wrap_result(FileWriter& file) const;
}; };

View File

@ -31,21 +31,21 @@ void StaticMethod::matlab_mfile(const string& toolboxPath, const string& classNa
// open destination m-file // open destination m-file
string full_name = className + "_" + name; string full_name = className + "_" + name;
string wrapperFile = toolboxPath + "/" + full_name + ".m"; string wrapperFile = toolboxPath + "/" + full_name + ".m";
ofstream ofs(wrapperFile.c_str()); FileWriter file(wrapperFile, "%");
if(!ofs) throw CantOpenFile(wrapperFile); // if(!file) throw CantOpenFile(wrapperFile);
if(verbose) cerr << "generating " << wrapperFile << endl; if(verbose) cerr << "generating " << wrapperFile << endl;
// generate code // generate code
string returnType = returnVal.matlab_returnType(); string returnType = returnVal.matlab_returnType();
ofs << "function " << returnType << " = " << full_name << "("; file.oss << "function " << returnType << " = " << full_name << "(";
if (args.size()) ofs << args.names(); if (args.size()) file.oss << args.names();
ofs << ")" << endl; file.oss << ")" << endl;
ofs << "% usage: x = " << full_name << "(" << args.names() << ")" << endl; file.oss << "% usage: x = " << full_name << "(" << args.names() << ")" << endl;
ofs << " error('need to compile " << full_name << ".cpp');" << endl; file.oss << " error('need to compile " << full_name << ".cpp');" << endl;
ofs << "end" << endl; file.oss << "end" << endl;
// close file // close file
ofs.close(); file.emit(false);
} }
/* ************************************************************************* */ /* ************************************************************************* */
@ -56,45 +56,45 @@ void StaticMethod::matlab_wrapper(const string& toolboxPath, const string& class
// open destination wrapperFile // open destination wrapperFile
string full_name = matlabClassName + "_" + name; string full_name = matlabClassName + "_" + name;
string wrapperFile = toolboxPath + "/" + full_name + ".cpp"; string wrapperFile = toolboxPath + "/" + full_name + ".cpp";
ofstream ofs(wrapperFile.c_str()); FileWriter file(wrapperFile, "%");
if(!ofs) throw CantOpenFile(wrapperFile); // if(!file) throw CantOpenFile(wrapperFile);
if(verbose) cerr << "generating " << wrapperFile << endl; if(verbose) cerr << "generating " << wrapperFile << endl;
// generate code // generate code
// header // header
generateHeaderComment(ofs, "//"); // generateHeaderComment(file, "//");
generateIncludes(ofs, className, includes); generateIncludes(file, className, includes);
generateUsingNamespace(ofs, using_namespaces); generateUsingNamespace(file, using_namespaces);
// call // call
ofs << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n"; file.oss << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n";
// start // start
ofs << "{\n"; file.oss << "{\n";
// check arguments // check arguments
// NOTE: for static functions, there is no object passed // NOTE: for static functions, there is no object passed
ofs << " checkArguments(\"" << full_name << "\",nargout,nargin," << args.size() << ");\n"; file.oss << " checkArguments(\"" << full_name << "\",nargout,nargin," << args.size() << ");\n";
// unwrap arguments, see Argument.cpp // unwrap arguments, see Argument.cpp
args.matlab_unwrap(ofs,0); // We start at 0 because there is no self object args.matlab_unwrap(file,0); // We start at 0 because there is no self object
ofs << " "; file.oss << " ";
// call method with default type // call method with default type
if (returnVal.type1!="void") if (returnVal.type1!="void")
ofs << returnVal.return_type(true,ReturnValue::pair) << " result = "; file.oss << returnVal.return_type(true,ReturnValue::pair) << " result = ";
ofs << cppClassName << "::" << name << "(" << args.names() << ");\n"; file.oss << cppClassName << "::" << name << "(" << args.names() << ");\n";
// wrap result // wrap result
// example: out[0]=wrap<bool>(result); // example: out[0]=wrap<bool>(result);
returnVal.wrap_result(ofs); returnVal.wrap_result(file);
// finish // finish
ofs << "}\n"; file.oss << "}\n";
// close file // close file
ofs.close(); file.emit(true);
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -17,14 +17,12 @@
#include <iostream> #include <iostream>
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include "utilities.h" #include "utilities.h"
namespace wrap { namespace wrap {
using namespace std; using namespace std;
using namespace boost::gregorian;
/* ************************************************************************* */ /* ************************************************************************* */
string file_contents(const string& filename, bool skipheader) { string file_contents(const string& filename, bool skipheader) {
@ -103,11 +101,11 @@ bool files_equal(const string& expected, const string& actual, bool skipheader)
return true; return true;
} }
/* ************************************************************************* */ ///* ************************************************************************* */
void generateHeaderComment(ofstream& ofs, const string& delimiter) { //void generateHeaderComment(FileWriter& file, const string& delimiter) {
date today = day_clock::local_day(); // date today = day_clock::local_day();
ofs << delimiter << " automatically generated by wrap on " << today << endl; // file.oss << delimiter << " automatically generated by wrap on " << today << endl;
} //}
/* ************************************************************************* */ /* ************************************************************************* */
string maybe_shared_ptr(bool add, const string& type) { string maybe_shared_ptr(bool add, const string& type) {
@ -118,25 +116,25 @@ string maybe_shared_ptr(bool add, const string& type) {
} }
/* ************************************************************************* */ /* ************************************************************************* */
void generateUsingNamespace(ofstream& ofs, const vector<string>& using_namespaces) { void generateUsingNamespace(FileWriter& file, const vector<string>& using_namespaces) {
if (using_namespaces.empty()) return; if (using_namespaces.empty()) return;
BOOST_FOREACH(const string& s, using_namespaces) BOOST_FOREACH(const string& s, using_namespaces)
ofs << "using namespace " << s << ";" << endl; file.oss << "using namespace " << s << ";" << endl;
} }
/* ************************************************************************* */ /* ************************************************************************* */
void generateIncludes(ofstream& ofs, const string& class_name, void generateIncludes(FileWriter& file, const string& class_name,
const vector<string>& includes) { const vector<string>& includes) {
ofs << "#include <wrap/matlab.h>" << endl; file.oss << "#include <wrap/matlab.h>" << endl;
bool added_include = false; bool added_include = false;
BOOST_FOREACH(const string& s, includes) { BOOST_FOREACH(const string& s, includes) {
if (!s.empty()) { if (!s.empty()) {
ofs << "#include <" << s << ">" << endl; file.oss << "#include <" << s << ">" << endl;
added_include = true; added_include = true;
} }
} }
if (!added_include) // add default include if (!added_include) // add default include
ofs << "#include <" << class_name << ".h>" << endl; file.oss << "#include <" << class_name << ".h>" << endl;
} }
/* ************************************************************************* */ /* ************************************************************************* */

View File

@ -21,6 +21,8 @@
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include "FileWriter.h"
namespace wrap { namespace wrap {
class CantOpenFile : public std::exception { class CantOpenFile : public std::exception {
@ -49,18 +51,18 @@ class ParseFailed : public std::exception {
}; };
class DependencyMissing : public std::exception { class DependencyMissing : public std::exception {
private: private:
std::string dependency_; std::string dependency_;
std::string location_; std::string location_;
public: public:
DependencyMissing(const std::string& dep, const std::string& loc) { DependencyMissing(const std::string& dep, const std::string& loc) {
dependency_ = dep; dependency_ = dep;
location_ = loc; location_ = loc;
} }
~DependencyMissing() throw() {} ~DependencyMissing() throw() {}
virtual const char* what() const throw() { virtual const char* what() const throw() {
return ("Missing dependency " + dependency_ + " in " + location_).c_str(); return ("Missing dependency " + dependency_ + " in " + location_).c_str();
} }
}; };
@ -83,7 +85,7 @@ bool assert_equal(const std::vector<std::string>& expected, const std::vector<st
/** /**
* emit a header at the top of generated files * emit a header at the top of generated files
*/ */
void generateHeaderComment(std::ofstream& ofs, const std::string& delimiter); //void generateHeaderComment(FileWriter& file, const std::string& delimiter);
// auxiliary function to wrap an argument into a shared_ptr template // auxiliary function to wrap an argument into a shared_ptr template
std::string maybe_shared_ptr(bool add, const std::string& type); std::string maybe_shared_ptr(bool add, const std::string& type);
@ -91,12 +93,12 @@ std::string maybe_shared_ptr(bool add, const std::string& type);
/** /**
* Creates the "using namespace [name];" declarations * Creates the "using namespace [name];" declarations
*/ */
void generateUsingNamespace(std::ofstream& ofs, const std::vector<std::string>& using_namespaces); void generateUsingNamespace(FileWriter& file, const std::vector<std::string>& using_namespaces);
/** /**
* Creates the #include statements * Creates the #include statements
*/ */
void generateIncludes(std::ofstream& ofs, const std::string& class_name, void generateIncludes(FileWriter& file, const std::string& class_name,
const std::vector<std::string>& includes); const std::vector<std::string>& includes);
} // \namespace wrap } // \namespace wrap