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 {
ofs << " ";
void Argument::matlab_unwrap(FileWriter& file, const string& matlabName) const {
file.oss << " ";
string cppType = qualifiedType("::");
string matlabType = qualifiedType();
if (is_ptr)
// 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)
// 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
// Not a pointer or a reference: emit an "unwrap" call
// unwrap is specified in matlab.h as a series of template specializations
// that know how to unpack the expected MATLAB object
// example: double tol = unwrap< double >(in[2]);
// example: Vector v = unwrap< Vector >(in[1]);
ofs << cppType << " " << name << " = unwrap< ";
file.oss << cppType << " " << name << " = unwrap< ";
ofs << cppType << " >(" << matlabName;
if (is_ptr || is_ref) ofs << ", \"" << matlabType << "\"";
ofs << ");" << endl;
file.oss << cppType << " >(" << matlabName;
if (is_ptr || is_ref) file.oss << ", \"" << matlabType << "\"";
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;
BOOST_FOREACH(Argument arg, *this) {
stringstream buf;
buf << "in[" << index << "]";
arg.matlab_unwrap(ofs,buf.str());
arg.matlab_unwrap(file,buf.str());
index++;
}
}

View File

@ -20,6 +20,8 @@
#include <string>
#include <vector>
#include "FileWriter.h"
namespace wrap {
/// Argument class
@ -40,7 +42,7 @@ struct Argument {
std::string qualifiedType(const std::string& delim = "") const;
/// 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
@ -59,10 +61,10 @@ struct ArgumentList: public std::vector<Argument> {
/**
* 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
*/
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

View File

@ -29,31 +29,31 @@ using namespace wrap;
/* ************************************************************************* */
void Class::matlab_proxy(const string& classFile) const {
// open destination classFile
ofstream ofs(classFile.c_str());
if(!ofs) throw CantOpenFile(classFile);
FileWriter file(classFile, "%");
// if(!file) 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 " << matlabName << endl;
ofs << " properties" << endl;
ofs << " self = 0" << endl;
ofs << " end" << endl;
ofs << " methods" << endl;
ofs << " function obj = " << matlabName << "(varargin)" << endl;
file.oss << "classdef " << matlabName << endl;
file.oss << " properties" << endl;
file.oss << " self = 0" << endl;
file.oss << " end" << endl;
file.oss << " methods" << endl;
file.oss << " function obj = " << matlabName << "(varargin)" << endl;
BOOST_FOREACH(Constructor c, constructors)
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;
ofs << " end" << endl;
ofs << "end" << endl;
c.matlab_proxy_fragment(file,matlabName);
file.oss << " if nargin ~= 13 && obj.self == 0, error('" << matlabName << " constructor failed'); end" << endl;
file.oss << " end" << endl;
file.oss << " function display(obj), obj.print(''); end" << endl;
file.oss << " function disp(obj), obj.display; end" << endl;
file.oss << " end" << endl;
file.oss << "end" << endl;
// 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& mexFlags) const {
string mex = "mex " + mexFlags + " ";
string matlabClassName = qualifiedName();
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)
ofs << mex << matlabClassName + "_" + sm.name << ".cpp" << endl;
ofs << endl << "cd @" << matlabClassName << endl;
file.oss << mex << matlabClassName + "_" + sm.name << ".cpp" << endl;
file.oss << endl << "cd @" << matlabClassName << endl;
BOOST_FOREACH(Method m, methods)
ofs << mex << m.name << ".cpp" << endl;
ofs << endl;
file.oss << mex << m.name << ".cpp" << endl;
file.oss << endl;
}
/* ************************************************************************* */
void Class::makefile_fragment(ofstream& ofs) const {
void Class::makefile_fragment(FileWriter& file) const {
// new_Point2_.$(MEXENDING): new_Point2_.cpp
// $(MEX) $(mex_flags) new_Point2_.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) {
ofs << file_base << ".$(MEXENDING): " << file_base << ".cpp" << endl;
ofs << "\t$(MEX) $(mex_flags) " << file_base << ".cpp -output " << file_base << endl;
file.oss << file_base << ".$(MEXENDING): " << file_base << ".cpp" << endl;
file.oss << "\t$(MEX) $(mex_flags) " << file_base << ".cpp -output " << file_base << endl;
}
// class target
ofs << "\n" << matlabName << ": ";
file.oss << "\n" << matlabName << ": ";
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
void matlab_static_methods(const std::string& classPath,
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& 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
};

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

View File

@ -30,21 +30,21 @@ void Method::matlab_mfile(const string& classPath) const {
// open destination m-file
string wrapperFile = classPath + "/" + name + ".m";
ofstream ofs(wrapperFile.c_str());
if(!ofs) throw CantOpenFile(wrapperFile);
FileWriter file(wrapperFile.c_str(), "%");
// if(!file) 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();
ofs << ")" << endl;
ofs << "% usage: obj." << name << "(" << args.names() << ")" << endl;
ofs << " error('need to compile " << name << ".cpp');" << endl;
ofs << "end" << endl;
file.oss << "function " << returnType << " = " << name << "(obj";
if (args.size()) file.oss << "," << args.names();
file.oss << ")" << endl;
file.oss << "% usage: obj." << name << "(" << args.names() << ")" << endl;
file.oss << " error('need to compile " << name << ".cpp');" << endl;
file.oss << "end" << endl;
// 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 {
// open destination wrapperFile
string wrapperFile = classPath + "/" + name + ".cpp";
ofstream ofs(wrapperFile.c_str());
if(!ofs) throw CantOpenFile(wrapperFile);
FileWriter file(wrapperFile.c_str(), "//");
// if(!file) throw CantOpenFile(wrapperFile);
if(verbose_) cerr << "generating " << wrapperFile << endl;
// generate code
// header
generateHeaderComment(ofs, "//");
generateIncludes(ofs, className, includes);
generateUsingNamespace(ofs, using_namespaces);
// generateHeaderComment(file, "//");
generateIncludes(file, className, includes);
generateUsingNamespace(file, using_namespaces);
// 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
ofs << "{\n";
file.oss << "{\n";
// 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";
file.oss << " 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<" << cppClassName << "> self = unwrap_shared_ptr< " << cppClassName
file.oss << " 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(file,1);
// call method
// example: bool result = self->return_field(t);
ofs << " ";
file.oss << " ";
if (returnVal.type1!="void")
ofs << returnVal.return_type(true,ReturnValue::pair) << " result = ";
ofs << "self->" << name << "(" << args.names() << ");\n";
file.oss << returnVal.return_type(true,ReturnValue::pair) << " result = ";
file.oss << "self->" << name << "(" << args.names() << ");\n";
// wrap result
// example: out[0]=wrap<bool>(result);
returnVal.wrap_result(ofs);
returnVal.wrap_result(file);
// finish
ofs << "}\n";
file.oss << "}\n";
// close file
ofs.close();
file.emit(true);
}
/* ************************************************************************* */

View File

@ -15,6 +15,7 @@
**/
#include "Module.h"
#include "FileWriter.h"
#include "utilities.h"
#include "spirit_actors.h"
@ -24,7 +25,7 @@
#include <boost/foreach.hpp>
#include <iostream>
#include <fstream>
//#include <fstream>
using namespace std;
using namespace wrap;
@ -279,29 +280,31 @@ void Module::matlab_code(const string& toolboxPath,
system(installCmd.c_str());
// create make m-file
string matlabMakeFile = toolboxPath + "/make_" + name + ".m";
ofstream ofs(matlabMakeFile.c_str());
if(!ofs) throw CantOpenFile(matlabMakeFile);
string matlabMakeFileName = toolboxPath + "/make_" + name + ".m";
FileWriter makeModuleMfile(matlabMakeFileName, "%");
// filetream makeModuleMfile(matlabMakeFileName.c_str());
// if(!makeModuleMfile) throw CantOpenFile(matlabMakeFileName);
// create the (actual) make file
string makeFile = toolboxPath + "/Makefile";
ofstream make_ofs(makeFile.c_str());
if(!make_ofs) throw CantOpenFile(makeFile);
string makeFileName = toolboxPath + "/Makefile";
FileWriter makeModuleMakefile(makeFileName, "#");
// filetream makeModuleMakefile(makeFileName.c_str());
// if(!makeModuleMakefile) throw CantOpenFile(makeFileName);
if (verbose) cerr << "generating " << matlabMakeFile << endl;
generateHeaderComment(ofs,"%");
ofs << "echo on" << endl << endl;
ofs << "toolboxpath = mfilename('fullpath');" << endl;
ofs << "delims = find(toolboxpath == '/');" << endl;
ofs << "toolboxpath = toolboxpath(1:(delims(end)-1));" << endl;
ofs << "clear delims" << endl;
ofs << "addpath(toolboxpath);" << endl << endl;
if (verbose) cerr << "generating " << matlabMakeFileName << endl;
// generateHeaderComment(makeModuleMfile,"%"); // In FileWriter constructor
makeModuleMfile.oss << "echo on" << endl << endl;
makeModuleMfile.oss << "toolboxpath = mfilename('fullpath');" << endl;
makeModuleMfile.oss << "delims = find(toolboxpath == '/');" << endl;
makeModuleMfile.oss << "toolboxpath = toolboxpath(1:(delims(end)-1));" << endl;
makeModuleMfile.oss << "clear delims" << endl;
makeModuleMfile.oss << "addpath(toolboxpath);" << endl << endl;
if (verbose) cerr << "generating " << makeFile << endl;
generateHeaderComment(make_ofs,"#");
make_ofs << "\nMEX = mex\n";
make_ofs << "MEXENDING = " << mexExt << "\n";
make_ofs << "mex_flags = " << mexFlags << "\n\n";
if (verbose) cerr << "generating " << makeFileName << endl;
// generateHeaderComment(makeModuleMakefile,"#"); // In FileWriter constructor
makeModuleMakefile.oss << "\nMEX = mex\n";
makeModuleMakefile.oss << "MEXENDING = " << mexExt << "\n";
makeModuleMakefile.oss << "mex_flags = " << mexFlags << "\n\n";
// Dependency check list
vector<string> validTypes = forward_declarations;
@ -315,13 +318,13 @@ void Module::matlab_code(const string& toolboxPath,
validTypes.push_back("Matrix");
// add 'all' to Makefile
make_ofs << "all: ";
makeModuleMakefile.oss << "all: ";
BOOST_FOREACH(Class cls, classes) {
make_ofs << cls.qualifiedName() << " ";
makeModuleMakefile.oss << cls.qualifiedName() << " ";
//Create a list of parsed classes for dependency checking
validTypes.push_back(cls.qualifiedName("::"));
}
make_ofs << "\n\n";
makeModuleMakefile.oss << "\n\n";
// generate proxy classes and wrappers
BOOST_FOREACH(Class cls, classes) {
@ -349,29 +352,31 @@ void Module::matlab_code(const string& toolboxPath,
cls.matlab_methods(classPath,using_namespaces);
// add lines to make m-file
ofs << "%% " << cls.qualifiedName() << endl;
ofs << "cd(toolboxpath)" << endl;
cls.matlab_make_fragment(ofs, toolboxPath, mexFlags);
makeModuleMfile.oss << "%% " << cls.qualifiedName() << endl;
makeModuleMfile.oss << "cd(toolboxpath)" << endl;
cls.matlab_make_fragment(makeModuleMfile, toolboxPath, mexFlags);
// add section to the (actual) make file
make_ofs << "# " << cls.qualifiedName() << endl;
cls.makefile_fragment(make_ofs);
makeModuleMakefile.oss << "# " << cls.qualifiedName() << endl;
cls.makefile_fragment(makeModuleMakefile);
}
// finish make m-file
ofs << "cd(toolboxpath)" << endl << endl;
ofs << "echo off" << endl;
ofs.close();
makeModuleMfile.oss << "cd(toolboxpath)" << endl << endl;
makeModuleMfile.oss << "echo off" << endl;
makeModuleMfile.emit(true); // By default, compare existing file first
// makeModuleMfile.emit();
// make clean at end of Makefile
make_ofs << "\n\nclean: \n";
make_ofs << "\trm -rf *.$(MEXENDING)\n";
makeModuleMakefile.oss << "\n\nclean: \n";
makeModuleMakefile.oss << "\trm -rf *.$(MEXENDING)\n";
BOOST_FOREACH(Class cls, classes)
make_ofs << "\trm -rf @" << cls.qualifiedName() << "/*.$(MEXENDING)\n";
makeModuleMakefile.oss << "\trm -rf @" << cls.qualifiedName() << "/*.$(MEXENDING)\n";
// finish Makefile
make_ofs << "\n" << endl;
make_ofs.close();
makeModuleMakefile.oss << "\n" << endl;
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 cppType2 = qualifiedType2("::"), matlabType2 = qualifiedType2();
if (isPair) {
// first return value in pair
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
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
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
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
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
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)
ofs << " out[0] = wrap_shared_ptr(result,\"" << type1 << "\");\n";
file.oss << " out[0] = wrap_shared_ptr(result,\"" << type1 << "\");\n";
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")
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 <ostream>
#include "FileWriter.h"
#pragma once
@ -46,7 +47,7 @@ struct ReturnValue {
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
string full_name = className + "_" + name;
string wrapperFile = toolboxPath + "/" + full_name + ".m";
ofstream ofs(wrapperFile.c_str());
if(!ofs) throw CantOpenFile(wrapperFile);
FileWriter file(wrapperFile, "%");
// if(!file) throw CantOpenFile(wrapperFile);
if(verbose) cerr << "generating " << wrapperFile << endl;
// generate code
string returnType = returnVal.matlab_returnType();
ofs << "function " << returnType << " = " << full_name << "(";
if (args.size()) ofs << args.names();
ofs << ")" << endl;
ofs << "% usage: x = " << full_name << "(" << args.names() << ")" << endl;
ofs << " error('need to compile " << full_name << ".cpp');" << endl;
ofs << "end" << endl;
file.oss << "function " << returnType << " = " << full_name << "(";
if (args.size()) file.oss << args.names();
file.oss << ")" << endl;
file.oss << "% usage: x = " << full_name << "(" << args.names() << ")" << endl;
file.oss << " error('need to compile " << full_name << ".cpp');" << endl;
file.oss << "end" << endl;
// close file
ofs.close();
file.emit(false);
}
/* ************************************************************************* */
@ -56,45 +56,45 @@ void StaticMethod::matlab_wrapper(const string& toolboxPath, const string& class
// open destination wrapperFile
string full_name = matlabClassName + "_" + name;
string wrapperFile = toolboxPath + "/" + full_name + ".cpp";
ofstream ofs(wrapperFile.c_str());
if(!ofs) throw CantOpenFile(wrapperFile);
FileWriter file(wrapperFile, "%");
// if(!file) throw CantOpenFile(wrapperFile);
if(verbose) cerr << "generating " << wrapperFile << endl;
// generate code
// header
generateHeaderComment(ofs, "//");
generateIncludes(ofs, className, includes);
generateUsingNamespace(ofs, using_namespaces);
// generateHeaderComment(file, "//");
generateIncludes(file, className, includes);
generateUsingNamespace(file, using_namespaces);
// 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
ofs << "{\n";
file.oss << "{\n";
// check arguments
// 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
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
if (returnVal.type1!="void")
ofs << returnVal.return_type(true,ReturnValue::pair) << " result = ";
ofs << cppClassName << "::" << name << "(" << args.names() << ");\n";
file.oss << returnVal.return_type(true,ReturnValue::pair) << " result = ";
file.oss << cppClassName << "::" << name << "(" << args.names() << ");\n";
// wrap result
// example: out[0]=wrap<bool>(result);
returnVal.wrap_result(ofs);
returnVal.wrap_result(file);
// finish
ofs << "}\n";
file.oss << "}\n";
// close file
ofs.close();
file.emit(true);
}
/* ************************************************************************* */

View File

@ -17,14 +17,12 @@
#include <iostream>
#include <boost/foreach.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
#include "utilities.h"
namespace wrap {
using namespace std;
using namespace boost::gregorian;
/* ************************************************************************* */
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;
}
/* ************************************************************************* */
void generateHeaderComment(ofstream& ofs, const string& delimiter) {
date today = day_clock::local_day();
ofs << delimiter << " automatically generated by wrap on " << today << endl;
}
///* ************************************************************************* */
//void generateHeaderComment(FileWriter& file, const string& delimiter) {
// date today = day_clock::local_day();
// file.oss << delimiter << " automatically generated by wrap on " << today << endl;
//}
/* ************************************************************************* */
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;
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) {
ofs << "#include <wrap/matlab.h>" << endl;
file.oss << "#include <wrap/matlab.h>" << endl;
bool added_include = false;
BOOST_FOREACH(const string& s, includes) {
if (!s.empty()) {
ofs << "#include <" << s << ">" << endl;
file.oss << "#include <" << s << ">" << endl;
added_include = true;
}
}
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 <sstream>
#include "FileWriter.h"
namespace wrap {
class CantOpenFile : public std::exception {
@ -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
*/
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
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
*/
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
*/
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);
} // \namespace wrap