Unified file writing to use a custom class to allow for smart checking
parent
ea1ef1fa85
commit
66a9d635b3
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
}
|
||||
/* ************************************************************************* */
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include "FileWriter.h"
|
||||
|
||||
namespace wrap {
|
||||
|
||||
class CantOpenFile : public std::exception {
|
||||
|
@ -49,18 +51,18 @@ class ParseFailed : public std::exception {
|
|||
};
|
||||
|
||||
class DependencyMissing : public std::exception {
|
||||
private:
|
||||
std::string dependency_;
|
||||
std::string location_;
|
||||
public:
|
||||
DependencyMissing(const std::string& dep, const std::string& loc) {
|
||||
dependency_ = dep;
|
||||
location_ = loc;
|
||||
}
|
||||
~DependencyMissing() throw() {}
|
||||
virtual const char* what() const throw() {
|
||||
return ("Missing dependency " + dependency_ + " in " + location_).c_str();
|
||||
}
|
||||
private:
|
||||
std::string dependency_;
|
||||
std::string location_;
|
||||
public:
|
||||
DependencyMissing(const std::string& dep, const std::string& loc) {
|
||||
dependency_ = dep;
|
||||
location_ = loc;
|
||||
}
|
||||
~DependencyMissing() throw() {}
|
||||
virtual const char* what() const throw() {
|
||||
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
|
||||
*/
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue