commit
fffad1336a
|
@ -122,13 +122,5 @@ struct ArgumentList: public std::vector<Argument> {
|
|||
|
||||
};
|
||||
|
||||
template<class T>
|
||||
inline void verifyArguments(const std::vector<std::string>& validArgs,
|
||||
const std::map<std::string, T>& vt) {
|
||||
typedef typename std::map<std::string, T>::value_type NamedMethod;
|
||||
BOOST_FOREACH(const NamedMethod& namedMethod, vt)
|
||||
namedMethod.second.verifyArguments(validArgs);
|
||||
}
|
||||
|
||||
} // \namespace wrap
|
||||
|
||||
|
|
|
@ -286,13 +286,13 @@ void Class::addMethod(bool verbose, bool is_const, Str methodName,
|
|||
// Now stick in new overload stack with expandedMethodName key
|
||||
// but note we use the same, unexpanded methodName in overload
|
||||
string expandedMethodName = methodName + instName.name;
|
||||
methods[expandedMethodName].addOverload(verbose, is_const, methodName,
|
||||
expandedArgs, expandedRetVal, instName);
|
||||
methods[expandedMethodName].addOverload(methodName, expandedArgs,
|
||||
expandedRetVal, is_const, instName, verbose);
|
||||
}
|
||||
} else
|
||||
// just add overload
|
||||
methods[methodName].addOverload(verbose, is_const, methodName, argumentList,
|
||||
returnValue);
|
||||
methods[methodName].addOverload(methodName, argumentList, returnValue,
|
||||
is_const, Qualified(), verbose);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
@ -583,4 +583,16 @@ string Class::getSerializationExport() const {
|
|||
return "BOOST_CLASS_EXPORT_GUID(" + qualifiedName("::") + ", \""
|
||||
+ qualifiedName() + "\");";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Class::python_wrapper(FileWriter& wrapperFile) const {
|
||||
wrapperFile.oss << "class_<" << name << ">(\"" << name << "\")\n";
|
||||
constructor.python_wrapper(wrapperFile, name);
|
||||
BOOST_FOREACH(const StaticMethod& m, static_methods | boost::adaptors::map_values)
|
||||
m.python_wrapper(wrapperFile, name);
|
||||
BOOST_FOREACH(const Method& m, methods | boost::adaptors::map_values)
|
||||
m.python_wrapper(wrapperFile, name);
|
||||
wrapperFile.oss << ";\n\n";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -111,6 +111,9 @@ public:
|
|||
void deserialization_fragments(FileWriter& proxyFile, FileWriter& wrapperFile,
|
||||
Str wrapperName, std::vector<std::string>& functionNames) const;
|
||||
|
||||
// emit python wrapper
|
||||
void python_wrapper(FileWriter& wrapperFile) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Class& cls) {
|
||||
os << "class " << cls.name << "{\n";
|
||||
os << cls.constructor << ";\n";
|
||||
|
|
|
@ -29,52 +29,55 @@
|
|||
using namespace std;
|
||||
using namespace wrap;
|
||||
|
||||
|
||||
/* ************************************************************************* */
|
||||
string Constructor::matlab_wrapper_name(const string& className) const {
|
||||
string Constructor::matlab_wrapper_name(Str className) const {
|
||||
string str = "new_" + className;
|
||||
return str;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Constructor::proxy_fragment(FileWriter& file, const std::string& wrapperName,
|
||||
bool hasParent, const int id, const ArgumentList args) const {
|
||||
void Constructor::proxy_fragment(FileWriter& file,
|
||||
const std::string& wrapperName, bool hasParent, const int id,
|
||||
const ArgumentList args) const {
|
||||
size_t nrArgs = args.size();
|
||||
// check for number of arguments...
|
||||
file.oss << " elseif nargin == " << nrArgs;
|
||||
if (nrArgs>0) file.oss << " && ";
|
||||
if (nrArgs > 0)
|
||||
file.oss << " && ";
|
||||
// ...and their types
|
||||
bool first = true;
|
||||
for(size_t i=0;i<nrArgs;i++) {
|
||||
if (!first) file.oss << " && ";
|
||||
file.oss << "isa(varargin{" << i+1 << "},'" << args[i].matlabClass(".") << "')";
|
||||
first=false;
|
||||
for (size_t i = 0; i < nrArgs; i++) {
|
||||
if (!first)
|
||||
file.oss << " && ";
|
||||
file.oss << "isa(varargin{" << i + 1 << "},'" << args[i].matlabClass(".")
|
||||
<< "')";
|
||||
first = false;
|
||||
}
|
||||
// emit code for calling constructor
|
||||
if(hasParent)
|
||||
if (hasParent)
|
||||
file.oss << "\n [ my_ptr, base_ptr ] = ";
|
||||
else
|
||||
file.oss << "\n my_ptr = ";
|
||||
file.oss << wrapperName << "(" << id;
|
||||
// emit constructor arguments
|
||||
for(size_t i=0;i<nrArgs;i++) {
|
||||
for (size_t i = 0; i < nrArgs; i++) {
|
||||
file.oss << ", ";
|
||||
file.oss << "varargin{" << i+1 << "}";
|
||||
file.oss << "varargin{" << i + 1 << "}";
|
||||
}
|
||||
file.oss << ");\n";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
string Constructor::wrapper_fragment(FileWriter& file,
|
||||
const string& cppClassName,
|
||||
const string& matlabUniqueName,
|
||||
const string& cppBaseClassName,
|
||||
int id,
|
||||
const ArgumentList& al) const {
|
||||
string Constructor::wrapper_fragment(FileWriter& file, Str cppClassName,
|
||||
Str matlabUniqueName, Str cppBaseClassName, int id,
|
||||
const ArgumentList& al) const {
|
||||
|
||||
const string wrapFunctionName = matlabUniqueName + "_constructor_" + boost::lexical_cast<string>(id);
|
||||
const string wrapFunctionName = matlabUniqueName + "_constructor_"
|
||||
+ boost::lexical_cast<string>(id);
|
||||
|
||||
file.oss << "void " << wrapFunctionName << "(int nargout, mxArray *out[], int nargin, const mxArray *in[])" << endl;
|
||||
file.oss << "void " << wrapFunctionName
|
||||
<< "(int nargout, mxArray *out[], int nargin, const mxArray *in[])"
|
||||
<< endl;
|
||||
file.oss << "{\n";
|
||||
file.oss << " mexAtExit(&_deleteAllObjects);\n";
|
||||
//Typedef boost::shared_ptr
|
||||
|
@ -82,22 +85,29 @@ string Constructor::wrapper_fragment(FileWriter& file,
|
|||
file.oss << "\n";
|
||||
|
||||
//Check to see if there will be any arguments and remove {} for consiseness
|
||||
if(al.size() > 0)
|
||||
if (al.size() > 0)
|
||||
al.matlab_unwrap(file); // unwrap arguments
|
||||
file.oss << " Shared *self = new Shared(new " << cppClassName << "(" << al.names() << "));" << endl;
|
||||
file.oss << " Shared *self = new Shared(new " << cppClassName << "("
|
||||
<< al.names() << "));" << endl;
|
||||
file.oss << " collector_" << matlabUniqueName << ".insert(self);\n";
|
||||
|
||||
if(verbose_)
|
||||
if (verbose_)
|
||||
file.oss << " std::cout << \"constructed \" << self << std::endl;" << endl;
|
||||
file.oss << " out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);" << endl;
|
||||
file.oss << " *reinterpret_cast<Shared**> (mxGetData(out[0])) = self;" << endl;
|
||||
file.oss
|
||||
<< " out[0] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);"
|
||||
<< endl;
|
||||
file.oss << " *reinterpret_cast<Shared**> (mxGetData(out[0])) = self;"
|
||||
<< endl;
|
||||
|
||||
// If we have a base class, return the base class pointer (MATLAB will call the base class collectorInsertAndMakeBase to add this to the collector and recurse the heirarchy)
|
||||
if(!cppBaseClassName.empty()) {
|
||||
if (!cppBaseClassName.empty()) {
|
||||
file.oss << "\n";
|
||||
file.oss << " typedef boost::shared_ptr<" << cppBaseClassName << "> SharedBase;\n";
|
||||
file.oss << " out[1] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);\n";
|
||||
file.oss << " *reinterpret_cast<SharedBase**>(mxGetData(out[1])) = new SharedBase(*self);\n";
|
||||
file.oss << " typedef boost::shared_ptr<" << cppBaseClassName
|
||||
<< "> SharedBase;\n";
|
||||
file.oss
|
||||
<< " out[1] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL);\n";
|
||||
file.oss
|
||||
<< " *reinterpret_cast<SharedBase**>(mxGetData(out[1])) = new SharedBase(*self);\n";
|
||||
}
|
||||
|
||||
file.oss << "}" << endl;
|
||||
|
@ -106,3 +116,9 @@ string Constructor::wrapper_fragment(FileWriter& file,
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Constructor::python_wrapper(FileWriter& wrapperFile, Str className) const {
|
||||
wrapperFile.oss << " .def(\"" << name_ << "\", &" << className << "::" << name_
|
||||
<< ");\n";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Function.h"
|
||||
#include "OverloadedFunction.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -26,21 +26,19 @@
|
|||
namespace wrap {
|
||||
|
||||
// Constructor class
|
||||
struct Constructor: public ArgumentOverloads {
|
||||
struct Constructor: public OverloadedFunction {
|
||||
|
||||
typedef const std::string& Str;
|
||||
|
||||
/// Constructor creates an empty class
|
||||
Constructor(bool verbose = false) :
|
||||
verbose_(verbose) {
|
||||
Constructor(bool verbose = false) {
|
||||
verbose_ = verbose;
|
||||
}
|
||||
|
||||
// Then the instance variables are set directly by the Module constructor
|
||||
std::string name;
|
||||
bool verbose_;
|
||||
|
||||
Constructor expandTemplate(const TemplateSubstitution& ts) const {
|
||||
Constructor inst = *this;
|
||||
inst.argLists_ = expandArgumentListsTemplate(ts);
|
||||
inst.name = ts.expandedClassName();
|
||||
inst.name_ = ts.expandedClassName();
|
||||
return inst;
|
||||
}
|
||||
|
||||
|
@ -49,14 +47,14 @@ struct Constructor: public ArgumentOverloads {
|
|||
// classFile is class proxy file, e.g., ../matlab/@Point2/Point2.m
|
||||
|
||||
/// wrapper name
|
||||
std::string matlab_wrapper_name(const std::string& className) const;
|
||||
std::string matlab_wrapper_name(Str className) const;
|
||||
|
||||
void comment_fragment(FileWriter& proxyFile) const {
|
||||
if (nrOverloads() > 0)
|
||||
proxyFile.oss << "%\n%-------Constructors-------\n";
|
||||
for (size_t i = 0; i < nrOverloads(); i++) {
|
||||
proxyFile.oss << "%";
|
||||
argumentList(i).emit_prototype(proxyFile, name);
|
||||
argumentList(i).emit_prototype(proxyFile, name_);
|
||||
proxyFile.oss << "\n";
|
||||
}
|
||||
}
|
||||
|
@ -65,22 +63,24 @@ struct Constructor: public ArgumentOverloads {
|
|||
* Create fragment to select constructor in proxy class, e.g.,
|
||||
* if nargin == 2, obj.self = new_Pose3_RP(varargin{1},varargin{2}); end
|
||||
*/
|
||||
void proxy_fragment(FileWriter& file, const std::string& wrapperName,
|
||||
bool hasParent, const int id, const ArgumentList args) const;
|
||||
void proxy_fragment(FileWriter& file, Str wrapperName, bool hasParent,
|
||||
const int id, const ArgumentList args) const;
|
||||
|
||||
/// cpp wrapper
|
||||
std::string wrapper_fragment(FileWriter& file,
|
||||
const std::string& cppClassName, const std::string& matlabUniqueName,
|
||||
const std::string& cppBaseClassName, int id,
|
||||
std::string wrapper_fragment(FileWriter& file, Str cppClassName,
|
||||
Str matlabUniqueName, Str cppBaseClassName, int id,
|
||||
const ArgumentList& al) const;
|
||||
|
||||
/// constructor function
|
||||
void generate_construct(FileWriter& file, const std::string& cppClassName,
|
||||
void generate_construct(FileWriter& file, Str cppClassName,
|
||||
std::vector<ArgumentList>& args_list) const;
|
||||
|
||||
// emit python wrapper
|
||||
void python_wrapper(FileWriter& wrapperFile, Str className) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Constructor& m) {
|
||||
for (size_t i = 0; i < m.nrOverloads(); i++)
|
||||
os << m.name << m.argLists_[i];
|
||||
os << m.name_ << m.argLists_[i];
|
||||
return os;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
||||
* Atlanta, Georgia 30332-0415
|
||||
* All Rights Reserved
|
||||
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
||||
|
||||
* See LICENSE for the license information
|
||||
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file FullyOverloadedFunction.h
|
||||
* @brief Function that can be fully overloaded: arguments and return values
|
||||
* @author Frank Dellaert
|
||||
* @date Nov 13, 2014
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "OverloadedFunction.h"
|
||||
|
||||
namespace wrap {
|
||||
|
||||
/**
|
||||
* Signature Overload (including return value)
|
||||
*/
|
||||
class SignatureOverloads: public ArgumentOverloads {
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<ReturnValue> returnVals_;
|
||||
|
||||
public:
|
||||
|
||||
const ReturnValue& returnValue(size_t i) const {
|
||||
return returnVals_.at(i);
|
||||
}
|
||||
|
||||
void push_back(const ArgumentList& args, const ReturnValue& retVal) {
|
||||
argLists_.push_back(args);
|
||||
returnVals_.push_back(retVal);
|
||||
}
|
||||
|
||||
void verifyReturnTypes(const std::vector<std::string>& validtypes,
|
||||
const std::string& s) const {
|
||||
BOOST_FOREACH(const ReturnValue& retval, returnVals_) {
|
||||
retval.type1.verify(validtypes, s);
|
||||
if (retval.isPair)
|
||||
retval.type2.verify(validtypes, s);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO use transform ?
|
||||
std::vector<ReturnValue> expandReturnValuesTemplate(
|
||||
const TemplateSubstitution& ts) const {
|
||||
std::vector<ReturnValue> result;
|
||||
BOOST_FOREACH(const ReturnValue& retVal, returnVals_) {
|
||||
ReturnValue instRetVal = retVal.expandTemplate(ts);
|
||||
result.push_back(instRetVal);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Expand templates, imperative !
|
||||
void expandTemplate(const TemplateSubstitution& ts) {
|
||||
// substitute template in arguments
|
||||
argLists_ = expandArgumentListsTemplate(ts);
|
||||
// do the same for return types
|
||||
returnVals_ = expandReturnValuesTemplate(ts);
|
||||
}
|
||||
|
||||
// emit a list of comments, one for each overload
|
||||
void usage_fragment(FileWriter& proxyFile, const std::string& name) const {
|
||||
unsigned int argLCount = 0;
|
||||
BOOST_FOREACH(ArgumentList argList, argLists_) {
|
||||
argList.emit_prototype(proxyFile, name);
|
||||
if (argLCount != nrOverloads() - 1)
|
||||
proxyFile.oss << ", ";
|
||||
else
|
||||
proxyFile.oss << " : returns " << returnValue(0).return_type(false)
|
||||
<< std::endl;
|
||||
argLCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// emit a list of comments, one for each overload
|
||||
void comment_fragment(FileWriter& proxyFile, const std::string& name) const {
|
||||
size_t i = 0;
|
||||
BOOST_FOREACH(ArgumentList argList, argLists_) {
|
||||
proxyFile.oss << "%";
|
||||
argList.emit_prototype(proxyFile, name);
|
||||
proxyFile.oss << " : returns " << returnVals_[i++].return_type(false)
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os,
|
||||
const SignatureOverloads& overloads) {
|
||||
for (size_t i = 0; i < overloads.nrOverloads(); i++)
|
||||
os << overloads.returnVals_[i] << overloads.argLists_[i] << std::endl;
|
||||
return os;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FullyOverloadedFunction: public Function, public SignatureOverloads {
|
||||
|
||||
public:
|
||||
|
||||
bool addOverload(const std::string& name, const ArgumentList& args,
|
||||
const ReturnValue& retVal, const Qualified& instName = Qualified(),
|
||||
bool verbose = false) {
|
||||
bool first = initializeOrCheck(name, instName, verbose);
|
||||
SignatureOverloads::push_back(args, retVal);
|
||||
return first;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Templated checking functions
|
||||
// TODO: do this via polymorphism, use transform ?
|
||||
|
||||
template<class F>
|
||||
inline void verifyReturnTypes(const std::vector<std::string>& validTypes,
|
||||
const std::map<std::string, F>& vt) {
|
||||
typedef typename std::map<std::string, F>::value_type NamedMethod;
|
||||
BOOST_FOREACH(const NamedMethod& namedMethod, vt)
|
||||
namedMethod.second.verifyReturnTypes(validTypes);
|
||||
}
|
||||
|
||||
} // \namespace wrap
|
||||
|
|
@ -29,38 +29,29 @@ using namespace std;
|
|||
using namespace wrap;
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Function::addOverload(bool verbose, const std::string& name,
|
||||
const Qualified& instName) {
|
||||
bool Function::initializeOrCheck(const std::string& name,
|
||||
const Qualified& instName, bool verbose) {
|
||||
|
||||
if (name.empty())
|
||||
throw std::runtime_error(
|
||||
"Function::initializeOrCheck called with empty name");
|
||||
|
||||
// Check if this overload is give to the correct method
|
||||
if (name_.empty())
|
||||
if (name_.empty()) {
|
||||
name_ = name;
|
||||
else if (name_ != name)
|
||||
throw std::runtime_error(
|
||||
"Function::addOverload: tried to add overload with name " + name
|
||||
+ " instead of expected " + name_);
|
||||
|
||||
// Check if this overload is give to the correct method
|
||||
if (templateArgValue_.empty())
|
||||
templateArgValue_ = instName;
|
||||
else if (templateArgValue_ != instName)
|
||||
throw std::runtime_error(
|
||||
"Function::addOverload: tried to add overload with template argument "
|
||||
+ instName.qualifiedName(":") + " instead of expected "
|
||||
+ templateArgValue_.qualifiedName(":"));
|
||||
verbose_ = verbose;
|
||||
return true;
|
||||
} else {
|
||||
if (name_ != name || templateArgValue_ != instName || verbose_ != verbose)
|
||||
throw std::runtime_error(
|
||||
"Function::initializeOrCheck called with different arguments: with name "
|
||||
+ name + " instead of expected " + name_
|
||||
+ ", or with template argument " + instName.qualifiedName(":")
|
||||
+ " instead of expected " + templateArgValue_.qualifiedName(":"));
|
||||
|
||||
verbose_ = verbose;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
vector<ArgumentList> ArgumentOverloads::expandArgumentListsTemplate(
|
||||
const TemplateSubstitution& ts) const {
|
||||
vector<ArgumentList> result;
|
||||
BOOST_FOREACH(const ArgumentList& argList, argLists_) {
|
||||
ArgumentList instArgList = argList.expandTemplate(ts);
|
||||
result.push_back(instArgList);
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
186
wrap/Function.h
186
wrap/Function.h
|
@ -19,11 +19,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Argument.h"
|
||||
#include "ReturnValue.h"
|
||||
#include "TypeAttributesTable.h"
|
||||
|
||||
#include <string>
|
||||
#include <list>
|
||||
|
||||
namespace wrap {
|
||||
|
||||
|
@ -32,20 +27,18 @@ class Function {
|
|||
|
||||
protected:
|
||||
|
||||
bool verbose_;
|
||||
std::string name_; ///< name of method
|
||||
Qualified templateArgValue_; ///< value of template argument if applicable
|
||||
bool verbose_;
|
||||
|
||||
public:
|
||||
|
||||
/// Constructor creates empty object
|
||||
Function(bool verbose = true) :
|
||||
verbose_(verbose) {
|
||||
}
|
||||
|
||||
Function(const std::string& name, bool verbose = true) :
|
||||
verbose_(verbose), name_(name) {
|
||||
}
|
||||
/**
|
||||
* @brief first time, fill in instance variables, otherwise check if same
|
||||
* @return true if first time, false thereafter
|
||||
*/
|
||||
bool initializeOrCheck(const std::string& name, const Qualified& instName =
|
||||
Qualified(), bool verbose = false);
|
||||
|
||||
std::string name() const {
|
||||
return name_;
|
||||
|
@ -57,172 +50,7 @@ public:
|
|||
else
|
||||
return name_ + templateArgValue_.name;
|
||||
}
|
||||
|
||||
// The first time this function is called, it initializes the class members
|
||||
// with those in rhs, but in subsequent calls it adds additional argument
|
||||
// lists as function overloads.
|
||||
void addOverload(bool verbose, const std::string& name,
|
||||
const Qualified& instName = Qualified());
|
||||
};
|
||||
|
||||
/**
|
||||
* ArgumentList Overloads
|
||||
*/
|
||||
class ArgumentOverloads {
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<ArgumentList> argLists_;
|
||||
|
||||
public:
|
||||
|
||||
size_t nrOverloads() const {
|
||||
return argLists_.size();
|
||||
}
|
||||
|
||||
const ArgumentList& argumentList(size_t i) const {
|
||||
return argLists_.at(i);
|
||||
}
|
||||
|
||||
void addOverload(const ArgumentList& args) {
|
||||
argLists_.push_back(args);
|
||||
}
|
||||
|
||||
std::vector<ArgumentList> expandArgumentListsTemplate(
|
||||
const TemplateSubstitution& ts) const;
|
||||
|
||||
/// Expand templates, imperative !
|
||||
virtual void ExpandTemplate(const TemplateSubstitution& ts) {
|
||||
argLists_ = expandArgumentListsTemplate(ts);
|
||||
}
|
||||
|
||||
void verifyArguments(const std::vector<std::string>& validArgs,
|
||||
const std::string s) const {
|
||||
BOOST_FOREACH(const ArgumentList& argList, argLists_) {
|
||||
BOOST_FOREACH(Argument arg, argList) {
|
||||
std::string fullType = arg.type.qualifiedName("::");
|
||||
if (find(validArgs.begin(), validArgs.end(), fullType)
|
||||
== validArgs.end())
|
||||
throw DependencyMissing(fullType, "checking argument of " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os,
|
||||
const ArgumentOverloads& overloads) {
|
||||
BOOST_FOREACH(const ArgumentList& argList, overloads.argLists_)
|
||||
os << argList << std::endl;
|
||||
return os;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Signature Overload (including return value)
|
||||
*/
|
||||
class SignatureOverloads: public ArgumentOverloads {
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<ReturnValue> returnVals_;
|
||||
|
||||
public:
|
||||
|
||||
const ReturnValue& returnValue(size_t i) const {
|
||||
return returnVals_.at(i);
|
||||
}
|
||||
|
||||
void addOverload(const ArgumentList& args, const ReturnValue& retVal) {
|
||||
argLists_.push_back(args);
|
||||
returnVals_.push_back(retVal);
|
||||
}
|
||||
|
||||
void verifyReturnTypes(const std::vector<std::string>& validtypes,
|
||||
const std::string& s) const {
|
||||
BOOST_FOREACH(const ReturnValue& retval, returnVals_) {
|
||||
retval.type1.verify(validtypes, s);
|
||||
if (retval.isPair)
|
||||
retval.type2.verify(validtypes, s);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO use transform ?
|
||||
std::vector<ReturnValue> expandReturnValuesTemplate(
|
||||
const TemplateSubstitution& ts) const {
|
||||
std::vector<ReturnValue> result;
|
||||
BOOST_FOREACH(const ReturnValue& retVal, returnVals_) {
|
||||
ReturnValue instRetVal = retVal.expandTemplate(ts);
|
||||
result.push_back(instRetVal);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Expand templates, imperative !
|
||||
void expandTemplate(const TemplateSubstitution& ts) {
|
||||
// substitute template in arguments
|
||||
argLists_ = expandArgumentListsTemplate(ts);
|
||||
// do the same for return types
|
||||
returnVals_ = expandReturnValuesTemplate(ts);
|
||||
}
|
||||
|
||||
// emit a list of comments, one for each overload
|
||||
void usage_fragment(FileWriter& proxyFile, const std::string& name) const {
|
||||
unsigned int argLCount = 0;
|
||||
BOOST_FOREACH(ArgumentList argList, argLists_) {
|
||||
argList.emit_prototype(proxyFile, name);
|
||||
if (argLCount != nrOverloads() - 1)
|
||||
proxyFile.oss << ", ";
|
||||
else
|
||||
proxyFile.oss << " : returns " << returnValue(0).return_type(false)
|
||||
<< std::endl;
|
||||
argLCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// emit a list of comments, one for each overload
|
||||
void comment_fragment(FileWriter& proxyFile, const std::string& name) const {
|
||||
size_t i = 0;
|
||||
BOOST_FOREACH(ArgumentList argList, argLists_) {
|
||||
proxyFile.oss << "%";
|
||||
argList.emit_prototype(proxyFile, name);
|
||||
proxyFile.oss << " : returns " << returnVals_[i++].return_type(false)
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os,
|
||||
const SignatureOverloads& overloads) {
|
||||
for (size_t i = 0; i < overloads.nrOverloads(); i++)
|
||||
os << overloads.returnVals_[i] << overloads.argLists_[i] << std::endl;
|
||||
return os;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Templated checking functions
|
||||
// TODO: do this via polymorphism ?
|
||||
|
||||
// TODO use transform
|
||||
template<class F>
|
||||
static std::map<std::string, F> expandMethodTemplate(
|
||||
const std::map<std::string, F>& methods, const TemplateSubstitution& ts) {
|
||||
std::map<std::string, F> result;
|
||||
typedef std::pair<const std::string, F> NamedMethod;
|
||||
BOOST_FOREACH(NamedMethod namedMethod, methods) {
|
||||
F instMethod = namedMethod.second;
|
||||
instMethod.expandTemplate(ts);
|
||||
namedMethod.second = instMethod;
|
||||
result.insert(namedMethod);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
template<class F>
|
||||
inline void verifyReturnTypes(const std::vector<std::string>& validTypes,
|
||||
const std::map<std::string, F>& vt) {
|
||||
typedef typename std::map<std::string, F>::value_type NamedMethod;
|
||||
BOOST_FOREACH(const NamedMethod& namedMethod, vt)
|
||||
namedMethod.second.verifyReturnTypes(validTypes);
|
||||
}
|
||||
|
||||
} // \namespace wrap
|
||||
|
||||
|
|
|
@ -16,18 +16,18 @@ namespace wrap {
|
|||
using namespace std;
|
||||
|
||||
/* ************************************************************************* */
|
||||
void GlobalFunction::addOverload(bool verbose, const Qualified& overload,
|
||||
void GlobalFunction::addOverload(const Qualified& overload,
|
||||
const ArgumentList& args, const ReturnValue& retVal,
|
||||
const Qualified& instName) {
|
||||
Function::addOverload(verbose, overload.name, instName);
|
||||
SignatureOverloads::addOverload(args, retVal);
|
||||
const Qualified& instName, bool verbose) {
|
||||
string name(overload.name);
|
||||
FullyOverloadedFunction::addOverload(name, args, retVal, instName, verbose);
|
||||
overloads.push_back(overload);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void GlobalFunction::matlab_proxy(const std::string& toolboxPath,
|
||||
const std::string& wrapperName, const TypeAttributesTable& typeAttributes,
|
||||
FileWriter& file, std::vector<std::string>& functionNames) const {
|
||||
void GlobalFunction::matlab_proxy(const string& toolboxPath,
|
||||
const string& wrapperName, const TypeAttributesTable& typeAttributes,
|
||||
FileWriter& file, vector<string>& functionNames) const {
|
||||
|
||||
// cluster overloads with same namespace
|
||||
// create new GlobalFunction structures around namespaces - same namespaces and names are overloads
|
||||
|
@ -40,8 +40,7 @@ void GlobalFunction::matlab_proxy(const std::string& toolboxPath,
|
|||
string str_ns = qualifiedName("", overload.namespaces);
|
||||
const ReturnValue& ret = returnValue(i);
|
||||
const ArgumentList& args = argumentList(i);
|
||||
grouped_functions[str_ns].addOverload(verbose_, overload, args, ret,
|
||||
templateArgValue_);
|
||||
grouped_functions[str_ns].addOverload(overload, args, ret);
|
||||
}
|
||||
|
||||
size_t lastcheck = grouped_functions.size();
|
||||
|
@ -54,9 +53,9 @@ void GlobalFunction::matlab_proxy(const std::string& toolboxPath,
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void GlobalFunction::generateSingleFunction(const std::string& toolboxPath,
|
||||
const std::string& wrapperName, const TypeAttributesTable& typeAttributes,
|
||||
FileWriter& file, std::vector<std::string>& functionNames) const {
|
||||
void GlobalFunction::generateSingleFunction(const string& toolboxPath,
|
||||
const string& wrapperName, const TypeAttributesTable& typeAttributes,
|
||||
FileWriter& file, vector<string>& functionNames) const {
|
||||
|
||||
// create the folder for the namespace
|
||||
const Qualified& overload1 = overloads.front();
|
||||
|
@ -128,6 +127,11 @@ void GlobalFunction::generateSingleFunction(const std::string& toolboxPath,
|
|||
mfunctionFile.emit(true);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void GlobalFunction::python_wrapper(FileWriter& wrapperFile) const {
|
||||
wrapperFile.oss << "def(\"" << name_ << "\", " << name_ << ");\n";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
} // \namespace wrap
|
||||
|
|
|
@ -9,23 +9,18 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Function.h"
|
||||
#include "FullyOverloadedFunction.h"
|
||||
|
||||
namespace wrap {
|
||||
|
||||
struct GlobalFunction: public Function, public SignatureOverloads {
|
||||
struct GlobalFunction: public FullyOverloadedFunction {
|
||||
|
||||
std::vector<Qualified> overloads; ///< Stack of qualified names
|
||||
|
||||
// Constructor only used in Module
|
||||
GlobalFunction(bool verbose = true) :
|
||||
Function(verbose) {
|
||||
}
|
||||
|
||||
// Used to reconstruct
|
||||
GlobalFunction(const std::string& name, bool verbose = true) :
|
||||
Function(name,verbose) {
|
||||
}
|
||||
// adds an overloaded version of this function,
|
||||
void addOverload(const Qualified& overload, const ArgumentList& args,
|
||||
const ReturnValue& retVal, const Qualified& instName = Qualified(),
|
||||
bool verbose = false);
|
||||
|
||||
void verifyArguments(const std::vector<std::string>& validArgs) const {
|
||||
SignatureOverloads::verifyArguments(validArgs, name_);
|
||||
|
@ -35,16 +30,14 @@ struct GlobalFunction: public Function, public SignatureOverloads {
|
|||
SignatureOverloads::verifyReturnTypes(validtypes, name_);
|
||||
}
|
||||
|
||||
// adds an overloaded version of this function,
|
||||
void addOverload(bool verbose, const Qualified& overload,
|
||||
const ArgumentList& args, const ReturnValue& retVal,
|
||||
const Qualified& instName = Qualified());
|
||||
|
||||
// codegen function called from Module to build the cpp and matlab versions of the function
|
||||
void matlab_proxy(const std::string& toolboxPath,
|
||||
const std::string& wrapperName, const TypeAttributesTable& typeAttributes,
|
||||
FileWriter& file, std::vector<std::string>& functionNames) const;
|
||||
|
||||
// emit python wrapper
|
||||
void python_wrapper(FileWriter& wrapperFile) const;
|
||||
|
||||
private:
|
||||
|
||||
// Creates a single global function - all in same namespace
|
||||
|
|
|
@ -29,17 +29,25 @@ using namespace std;
|
|||
using namespace wrap;
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Method::addOverload(bool verbose, bool is_const, Str name,
|
||||
const ArgumentList& args, const ReturnValue& retVal,
|
||||
const Qualified& instName) {
|
||||
|
||||
StaticMethod::addOverload(verbose, name, args, retVal, instName);
|
||||
is_const_ = is_const;
|
||||
bool Method::addOverload(Str name, const ArgumentList& args,
|
||||
const ReturnValue& retVal, bool is_const, const Qualified& instName,
|
||||
bool verbose) {
|
||||
bool first = StaticMethod::addOverload(name, args, retVal, instName, verbose);
|
||||
if (first)
|
||||
is_const_ = is_const;
|
||||
else if (is_const && !is_const_)
|
||||
throw std::runtime_error(
|
||||
"Method::addOverload now designated as const whereas before it was not");
|
||||
else if (!is_const && is_const_)
|
||||
throw std::runtime_error(
|
||||
"Method::addOverload now designated as non-const whereas before it was");
|
||||
return first;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Method::proxy_header(FileWriter& proxyFile) const {
|
||||
proxyFile.oss << " function varargout = " << matlabName() << "(this, varargin)\n";
|
||||
proxyFile.oss << " function varargout = " << matlabName()
|
||||
<< "(this, varargin)\n";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -31,14 +31,9 @@ public:
|
|||
|
||||
typedef const std::string& Str;
|
||||
|
||||
/// Constructor creates empty object
|
||||
Method(bool verbose = true) :
|
||||
StaticMethod(verbose), is_const_(false) {
|
||||
}
|
||||
|
||||
Method(const std::string& name, bool verbose = true) :
|
||||
StaticMethod(name,verbose), is_const_(false) {
|
||||
}
|
||||
bool addOverload(Str name, const ArgumentList& args,
|
||||
const ReturnValue& retVal, bool is_const, const Qualified& instName =
|
||||
Qualified(), bool verbose = false);
|
||||
|
||||
virtual bool isStatic() const {
|
||||
return false;
|
||||
|
@ -48,13 +43,6 @@ public:
|
|||
return is_const_;
|
||||
}
|
||||
|
||||
// The first time this function is called, it initializes the class members
|
||||
// with those in rhs, but in subsequent calls it adds additional argument
|
||||
// lists as function overloads.
|
||||
void addOverload(bool verbose, bool is_const, Str name,
|
||||
const ArgumentList& args, const ReturnValue& retVal,
|
||||
const Qualified& instName = Qualified());
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Method& m) {
|
||||
for (size_t i = 0; i < m.nrOverloads(); i++)
|
||||
os << m.returnVals_[i] << " " << m.name_ << m.argLists_[i];
|
||||
|
|
107
wrap/Module.cpp
107
wrap/Module.cpp
|
@ -217,7 +217,7 @@ void Module::parseMarkup(const std::string& data) {
|
|||
Constructor constructor0(verbose), constructor(verbose);
|
||||
Rule constructor_p =
|
||||
(className_p >> '(' >> argumentList_p >> ')' >> ';' >> !comments_p)
|
||||
[bl::bind(&Constructor::addOverload, bl::var(constructor), bl::var(args))]
|
||||
[bl::bind(&Constructor::push_back, bl::var(constructor), bl::var(args))]
|
||||
[clear_a(args)];
|
||||
|
||||
vector<string> namespaces_return; /// namespace for current return type
|
||||
|
@ -274,7 +274,7 @@ void Module::parseMarkup(const std::string& data) {
|
|||
'(' >> argumentList_p >> ')' >> ';' >> *comments_p)
|
||||
[bl::bind(&StaticMethod::addOverload,
|
||||
bl::var(cls.static_methods)[bl::var(methodName)],
|
||||
verbose, bl::var(methodName), bl::var(args), bl::var(retVal), Qualified())]
|
||||
bl::var(methodName), bl::var(args), bl::var(retVal), Qualified(),verbose)]
|
||||
[assign_a(retVal,retVal0)]
|
||||
[clear_a(args)];
|
||||
|
||||
|
@ -295,7 +295,8 @@ void Module::parseMarkup(const std::string& data) {
|
|||
>> ((':' >> classParent_p >> '{') | '{')
|
||||
>> *(functions_p | comments_p)
|
||||
>> str_p("};"))
|
||||
[assign_a(constructor.name, cls.name)]
|
||||
[bl::bind(&Constructor::initializeOrCheck, bl::var(constructor),
|
||||
bl::var(cls.name), Qualified(), verbose)]
|
||||
[assign_a(cls.constructor, constructor)]
|
||||
[assign_a(cls.namespaces, namespaces)]
|
||||
[assign_a(cls.deconstructor.name,cls.name)]
|
||||
|
@ -313,7 +314,7 @@ void Module::parseMarkup(const std::string& data) {
|
|||
[assign_a(globalFunction.namespaces,namespaces)]
|
||||
[bl::bind(&GlobalFunction::addOverload,
|
||||
bl::var(global_functions)[bl::var(globalFunction.name)],
|
||||
verbose, bl::var(globalFunction), bl::var(args), bl::var(retVal), Qualified())]
|
||||
bl::var(globalFunction), bl::var(args), bl::var(retVal), Qualified(),verbose)]
|
||||
[assign_a(retVal,retVal0)]
|
||||
[clear_a(globalFunction)]
|
||||
[clear_a(args)];
|
||||
|
@ -393,51 +394,35 @@ void Module::parseMarkup(const std::string& data) {
|
|||
// Explicitly add methods to the classes from parents so it shows in documentation
|
||||
BOOST_FOREACH(Class& cls, classes)
|
||||
cls.appendInheritedMethods(cls, classes);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Module::generateIncludes(FileWriter& file) const {
|
||||
|
||||
// collect includes
|
||||
vector<string> all_includes(includes);
|
||||
|
||||
// sort and remove duplicates
|
||||
sort(all_includes.begin(), all_includes.end());
|
||||
vector<string>::const_iterator last_include = unique(all_includes.begin(), all_includes.end());
|
||||
vector<string>::const_iterator it = all_includes.begin();
|
||||
// add includes to file
|
||||
for (; it != last_include; ++it)
|
||||
file.oss << "#include <" << *it << ">" << endl;
|
||||
file.oss << "\n";
|
||||
}
|
||||
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Module::matlab_code(const string& toolboxPath, const string& headerPath) const {
|
||||
|
||||
fs::create_directories(toolboxPath);
|
||||
|
||||
// Expand templates - This is done first so that template instantiations are
|
||||
// counted in the list of valid types, have their attributes and dependencies
|
||||
// checked, etc.
|
||||
vector<Class> expandedClasses = ExpandTypedefInstantiations(classes, templateInstantiationTypedefs);
|
||||
expandedClasses = ExpandTypedefInstantiations(classes,
|
||||
templateInstantiationTypedefs);
|
||||
|
||||
// Dependency check list
|
||||
vector<string> validTypes = GenerateValidTypes(expandedClasses, forward_declarations);
|
||||
vector<string> validTypes = GenerateValidTypes(expandedClasses,
|
||||
forward_declarations);
|
||||
|
||||
// Check that all classes have been defined somewhere
|
||||
verifyArguments<GlobalFunction>(validTypes, global_functions);
|
||||
verifyReturnTypes<GlobalFunction>(validTypes, global_functions);
|
||||
|
||||
bool hasSerialiable = false;
|
||||
hasSerialiable = false;
|
||||
BOOST_FOREACH(const Class& cls, expandedClasses)
|
||||
cls.verifyAll(validTypes,hasSerialiable);
|
||||
|
||||
// Create type attributes table and check validity
|
||||
TypeAttributesTable typeAttributes;
|
||||
typeAttributes.addClasses(expandedClasses);
|
||||
typeAttributes.addForwardDeclarations(forward_declarations);
|
||||
typeAttributes.checkValidity(expandedClasses);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Module::matlab_code(const string& toolboxPath) const {
|
||||
|
||||
fs::create_directories(toolboxPath);
|
||||
|
||||
// create the unified .cpp switch file
|
||||
const string wrapperName = name + "_wrapper";
|
||||
|
@ -458,19 +443,18 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
|
|||
// Generate includes while avoiding redundant includes
|
||||
generateIncludes(wrapperFile);
|
||||
|
||||
// create typedef classes - we put this at the top of the wrap file so that collectors and method arguments can use these typedefs
|
||||
BOOST_FOREACH(const Class& cls, expandedClasses) {
|
||||
// create typedef classes - we put this at the top of the wrap file so that
|
||||
// collectors and method arguments can use these typedefs
|
||||
BOOST_FOREACH(const Class& cls, expandedClasses)
|
||||
if(!cls.typedefName.empty())
|
||||
wrapperFile.oss << cls.getTypedef() << "\n";
|
||||
}
|
||||
wrapperFile.oss << "\n";
|
||||
|
||||
// Generate boost.serialization export flags (needs typedefs from above)
|
||||
if (hasSerialiable) {
|
||||
BOOST_FOREACH(const Class& cls, expandedClasses) {
|
||||
BOOST_FOREACH(const Class& cls, expandedClasses)
|
||||
if(cls.isSerializable)
|
||||
wrapperFile.oss << cls.getSerializationExport() << "\n";
|
||||
}
|
||||
wrapperFile.oss << "\n";
|
||||
}
|
||||
|
||||
|
@ -483,14 +467,12 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
|
|||
vector<string> functionNames; // Function names stored by index for switch
|
||||
|
||||
// create proxy class and wrapper code
|
||||
BOOST_FOREACH(const Class& cls, expandedClasses) {
|
||||
BOOST_FOREACH(const Class& cls, expandedClasses)
|
||||
cls.matlab_proxy(toolboxPath, wrapperName, typeAttributes, wrapperFile, functionNames);
|
||||
}
|
||||
|
||||
// create matlab files and wrapper code for global functions
|
||||
BOOST_FOREACH(const GlobalFunctions::value_type& p, global_functions) {
|
||||
BOOST_FOREACH(const GlobalFunctions::value_type& p, global_functions)
|
||||
p.second.matlab_proxy(toolboxPath, wrapperName, typeAttributes, wrapperFile, functionNames);
|
||||
}
|
||||
|
||||
// finish wrapper file
|
||||
wrapperFile.oss << "\n";
|
||||
|
@ -500,6 +482,23 @@ void Module::matlab_code(const string& toolboxPath, const string& headerPath) co
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Module::generateIncludes(FileWriter& file) const {
|
||||
|
||||
// collect includes
|
||||
vector<string> all_includes(includes);
|
||||
|
||||
// sort and remove duplicates
|
||||
sort(all_includes.begin(), all_includes.end());
|
||||
vector<string>::const_iterator last_include = unique(all_includes.begin(), all_includes.end());
|
||||
vector<string>::const_iterator it = all_includes.begin();
|
||||
// add includes to file
|
||||
for (; it != last_include; ++it)
|
||||
file.oss << "#include <" << *it << ">" << endl;
|
||||
file.oss << "\n";
|
||||
}
|
||||
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Module::finish_wrapper(FileWriter& file, const std::vector<std::string>& functionNames) const {
|
||||
file.oss << "void mexFunction(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n";
|
||||
file.oss << "{\n";
|
||||
|
@ -651,3 +650,31 @@ void Module::WriteRTTIRegistry(FileWriter& wrapperFile, const std::string& modul
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void Module::python_wrapper(const string& toolboxPath) const {
|
||||
|
||||
fs::create_directories(toolboxPath);
|
||||
|
||||
// create the unified .cpp switch file
|
||||
const string wrapperName = name + "_python";
|
||||
string wrapperFileName = toolboxPath + "/" + wrapperName + ".cpp";
|
||||
FileWriter wrapperFile(wrapperFileName, verbose, "//");
|
||||
wrapperFile.oss << "#include <boost/python.hpp>\n\n";
|
||||
wrapperFile.oss << "using namespace boost::python;\n";
|
||||
wrapperFile.oss << "BOOST_PYTHON_MODULE(" + name + ")\n";
|
||||
wrapperFile.oss << "{\n";
|
||||
|
||||
// write out classes
|
||||
BOOST_FOREACH(const Class& cls, expandedClasses)
|
||||
cls.python_wrapper(wrapperFile);
|
||||
|
||||
// write out global functions
|
||||
BOOST_FOREACH(const GlobalFunctions::value_type& p, global_functions)
|
||||
p.second.python_wrapper(wrapperFile);
|
||||
|
||||
// finish wrapper file
|
||||
wrapperFile.oss << "}\n";
|
||||
|
||||
wrapperFile.emit(true);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -37,40 +37,53 @@ struct Module {
|
|||
typedef std::map<std::string, GlobalFunction> GlobalFunctions;
|
||||
typedef std::map<std::string, Method> Methods;
|
||||
|
||||
std::string name; ///< module name
|
||||
bool verbose; ///< verbose flag
|
||||
// Filled during parsing:
|
||||
std::string name; ///< module name
|
||||
bool verbose; ///< verbose flag
|
||||
std::vector<Class> classes; ///< list of classes
|
||||
std::vector<TemplateInstantiationTypedef> templateInstantiationTypedefs; ///< list of template instantiations
|
||||
std::vector<ForwardDeclaration> forward_declarations;
|
||||
std::vector<std::string> includes; ///< Include statements
|
||||
std::vector<std::string> includes; ///< Include statements
|
||||
GlobalFunctions global_functions;
|
||||
|
||||
// After parsing:
|
||||
std::vector<Class> expandedClasses;
|
||||
bool hasSerialiable;
|
||||
TypeAttributesTable typeAttributes;
|
||||
|
||||
/// constructor that parses interface file
|
||||
Module(const std::string& interfacePath,
|
||||
const std::string& moduleName,
|
||||
bool enable_verbose=true);
|
||||
Module(const std::string& interfacePath, const std::string& moduleName,
|
||||
bool enable_verbose = true);
|
||||
|
||||
/// Dummy constructor that does no parsing - use only for testing
|
||||
Module(const std::string& moduleName, bool enable_verbose=true);
|
||||
|
||||
/// MATLAB code generation:
|
||||
void matlab_code(
|
||||
const std::string& path,
|
||||
const std::string& headerPath) const; // FIXME: headerPath not actually used?
|
||||
|
||||
void finish_wrapper(FileWriter& file, const std::vector<std::string>& functionNames) const;
|
||||
|
||||
void generateIncludes(FileWriter& file) const;
|
||||
Module(const std::string& moduleName, bool enable_verbose = true);
|
||||
|
||||
/// non-const function that performs parsing - typically called by constructor
|
||||
/// Throws exception on failure
|
||||
void parseMarkup(const std::string& data);
|
||||
|
||||
/// MATLAB code generation:
|
||||
void matlab_code(const std::string& path) const;
|
||||
|
||||
void generateIncludes(FileWriter& file) const;
|
||||
|
||||
void finish_wrapper(FileWriter& file,
|
||||
const std::vector<std::string>& functionNames) const;
|
||||
|
||||
/// Python code generation:
|
||||
void python_wrapper(const std::string& path) const;
|
||||
|
||||
private:
|
||||
static std::vector<Class> ExpandTypedefInstantiations(const std::vector<Class>& classes, const std::vector<TemplateInstantiationTypedef> instantiations);
|
||||
static std::vector<std::string> GenerateValidTypes(const std::vector<Class>& classes, const std::vector<ForwardDeclaration> forwardDeclarations);
|
||||
static void WriteCollectorsAndCleanupFcn(FileWriter& wrapperFile, const std::string& moduleName, const std::vector<Class>& classes);
|
||||
static void WriteRTTIRegistry(FileWriter& wrapperFile, const std::string& moduleName, const std::vector<Class>& classes);
|
||||
static std::vector<Class> ExpandTypedefInstantiations(
|
||||
const std::vector<Class>& classes,
|
||||
const std::vector<TemplateInstantiationTypedef> instantiations);
|
||||
static std::vector<std::string> GenerateValidTypes(
|
||||
const std::vector<Class>& classes,
|
||||
const std::vector<ForwardDeclaration> forwardDeclarations);
|
||||
static void WriteCollectorsAndCleanupFcn(FileWriter& wrapperFile,
|
||||
const std::string& moduleName, const std::vector<Class>& classes);
|
||||
static void WriteRTTIRegistry(FileWriter& wrapperFile,
|
||||
const std::string& moduleName, const std::vector<Class>& classes);
|
||||
};
|
||||
|
||||
} // \namespace wrap
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
|
||||
* GTSAM Copyright 2010, Georgia Tech Research Corporation,
|
||||
* Atlanta, Georgia 30332-0415
|
||||
* All Rights Reserved
|
||||
* Authors: Frank Dellaert, et al. (see THANKS for the full author list)
|
||||
|
||||
* See LICENSE for the license information
|
||||
|
||||
* -------------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* @file OverloadedFunction.h
|
||||
* @brief Function that can overload its arguments only
|
||||
* @author Frank Dellaert
|
||||
* @date Nov 13, 2014
|
||||
**/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Function.h"
|
||||
#include "Argument.h"
|
||||
|
||||
namespace wrap {
|
||||
|
||||
/**
|
||||
* ArgumentList Overloads
|
||||
*/
|
||||
class ArgumentOverloads {
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<ArgumentList> argLists_;
|
||||
|
||||
public:
|
||||
|
||||
size_t nrOverloads() const {
|
||||
return argLists_.size();
|
||||
}
|
||||
|
||||
const ArgumentList& argumentList(size_t i) const {
|
||||
return argLists_.at(i);
|
||||
}
|
||||
|
||||
void push_back(const ArgumentList& args) {
|
||||
argLists_.push_back(args);
|
||||
}
|
||||
|
||||
std::vector<ArgumentList> expandArgumentListsTemplate(
|
||||
const TemplateSubstitution& ts) const {
|
||||
std::vector<ArgumentList> result;
|
||||
BOOST_FOREACH(const ArgumentList& argList, argLists_) {
|
||||
ArgumentList instArgList = argList.expandTemplate(ts);
|
||||
result.push_back(instArgList);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Expand templates, imperative !
|
||||
virtual void ExpandTemplate(const TemplateSubstitution& ts) {
|
||||
argLists_ = expandArgumentListsTemplate(ts);
|
||||
}
|
||||
|
||||
void verifyArguments(const std::vector<std::string>& validArgs,
|
||||
const std::string s) const {
|
||||
BOOST_FOREACH(const ArgumentList& argList, argLists_) {
|
||||
BOOST_FOREACH(Argument arg, argList) {
|
||||
std::string fullType = arg.type.qualifiedName("::");
|
||||
if (find(validArgs.begin(), validArgs.end(), fullType)
|
||||
== validArgs.end())
|
||||
throw DependencyMissing(fullType, "checking argument of " + s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os,
|
||||
const ArgumentOverloads& overloads) {
|
||||
BOOST_FOREACH(const ArgumentList& argList, overloads.argLists_)
|
||||
os << argList << std::endl;
|
||||
return os;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class OverloadedFunction: public Function, public ArgumentOverloads {
|
||||
|
||||
public:
|
||||
|
||||
bool addOverload(const std::string& name, const ArgumentList& args,
|
||||
const Qualified& instName = Qualified(), bool verbose = false) {
|
||||
bool first = initializeOrCheck(name, instName, verbose);
|
||||
ArgumentOverloads::push_back(args);
|
||||
return first;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
// Templated checking functions
|
||||
// TODO: do this via polymorphism, use transform ?
|
||||
|
||||
template<class F>
|
||||
static std::map<std::string, F> expandMethodTemplate(
|
||||
const std::map<std::string, F>& methods, const TemplateSubstitution& ts) {
|
||||
std::map<std::string, F> result;
|
||||
typedef std::pair<const std::string, F> NamedMethod;
|
||||
BOOST_FOREACH(NamedMethod namedMethod, methods) {
|
||||
F instMethod = namedMethod.second;
|
||||
instMethod.expandTemplate(ts);
|
||||
namedMethod.second = instMethod;
|
||||
result.insert(namedMethod);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class F>
|
||||
inline void verifyArguments(const std::vector<std::string>& validArgs,
|
||||
const std::map<std::string, F>& vt) {
|
||||
typedef typename std::map<std::string, F>::value_type NamedMethod;
|
||||
BOOST_FOREACH(const NamedMethod& namedMethod, vt)
|
||||
namedMethod.second.verifyArguments(validArgs);
|
||||
}
|
||||
|
||||
} // \namespace wrap
|
||||
|
|
@ -29,14 +29,6 @@
|
|||
using namespace std;
|
||||
using namespace wrap;
|
||||
|
||||
/* ************************************************************************* */
|
||||
void StaticMethod::addOverload(bool verbose, Str name, const ArgumentList& args,
|
||||
const ReturnValue& retVal, const Qualified& instName) {
|
||||
|
||||
Function::addOverload(verbose, name, instName);
|
||||
SignatureOverloads::addOverload(args, retVal);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void StaticMethod::proxy_header(FileWriter& proxyFile) const {
|
||||
string upperName = matlabName();
|
||||
|
@ -173,3 +165,10 @@ string StaticMethod::wrapper_call(FileWriter& wrapperFile, Str cppClassName,
|
|||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
void StaticMethod::python_wrapper(FileWriter& wrapperFile,
|
||||
Str className) const {
|
||||
wrapperFile.oss << " .def(\"" << name_ << "\", &" << className << "::" << name_
|
||||
<< ");\n";
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -19,31 +19,19 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Function.h"
|
||||
#include "FullyOverloadedFunction.h"
|
||||
|
||||
namespace wrap {
|
||||
|
||||
/// StaticMethod class
|
||||
struct StaticMethod: public Function, public SignatureOverloads {
|
||||
struct StaticMethod: public FullyOverloadedFunction {
|
||||
|
||||
typedef const std::string& Str;
|
||||
|
||||
/// Constructor creates empty object
|
||||
StaticMethod(bool verbosity = true) :
|
||||
Function(verbosity) {
|
||||
}
|
||||
|
||||
StaticMethod(const std::string& name, bool verbose = true) :
|
||||
Function(name,verbose) {
|
||||
}
|
||||
|
||||
virtual bool isStatic() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void addOverload(bool verbose, Str name, const ArgumentList& args,
|
||||
const ReturnValue& retVal, const Qualified& instName);
|
||||
|
||||
// emit a list of comments, one for each overload
|
||||
void comment_fragment(FileWriter& proxyFile) const {
|
||||
SignatureOverloads::comment_fragment(proxyFile, matlabName());
|
||||
|
@ -64,6 +52,9 @@ struct StaticMethod: public Function, public SignatureOverloads {
|
|||
Str wrapperName, const TypeAttributesTable& typeAttributes,
|
||||
std::vector<std::string>& functionNames) const;
|
||||
|
||||
// emit python wrapper
|
||||
void python_wrapper(FileWriter& wrapperFile, Str className) const;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const StaticMethod& m) {
|
||||
for (size_t i = 0; i < m.nrOverloads(); i++)
|
||||
os << "static " << m.returnVals_[i] << " " << m.name_ << m.argLists_[i];
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
#include <boost/python.hpp>
|
||||
|
||||
using namespace boost::python;
|
||||
BOOST_PYTHON_MODULE(geometry)
|
||||
{
|
||||
class_<Point2>("Point2")
|
||||
.def("Point2", &Point2::Point2);
|
||||
.def("argChar", &Point2::argChar);
|
||||
.def("argUChar", &Point2::argUChar);
|
||||
.def("dim", &Point2::dim);
|
||||
.def("returnChar", &Point2::returnChar);
|
||||
.def("vectorConfusion", &Point2::vectorConfusion);
|
||||
.def("x", &Point2::x);
|
||||
.def("y", &Point2::y);
|
||||
;
|
||||
|
||||
class_<Point3>("Point3")
|
||||
.def("Point3", &Point3::Point3);
|
||||
.def("StaticFunctionRet", &Point3::StaticFunctionRet);
|
||||
.def("staticFunction", &Point3::staticFunction);
|
||||
.def("norm", &Point3::norm);
|
||||
;
|
||||
|
||||
class_<Test>("Test")
|
||||
.def("Test", &Test::Test);
|
||||
.def("arg_EigenConstRef", &Test::arg_EigenConstRef);
|
||||
.def("create_MixedPtrs", &Test::create_MixedPtrs);
|
||||
.def("create_ptrs", &Test::create_ptrs);
|
||||
.def("print", &Test::print);
|
||||
.def("return_Point2Ptr", &Test::return_Point2Ptr);
|
||||
.def("return_Test", &Test::return_Test);
|
||||
.def("return_TestPtr", &Test::return_TestPtr);
|
||||
.def("return_bool", &Test::return_bool);
|
||||
.def("return_double", &Test::return_double);
|
||||
.def("return_field", &Test::return_field);
|
||||
.def("return_int", &Test::return_int);
|
||||
.def("return_matrix1", &Test::return_matrix1);
|
||||
.def("return_matrix2", &Test::return_matrix2);
|
||||
.def("return_pair", &Test::return_pair);
|
||||
.def("return_ptrs", &Test::return_ptrs);
|
||||
.def("return_size_t", &Test::return_size_t);
|
||||
.def("return_string", &Test::return_string);
|
||||
.def("return_vector1", &Test::return_vector1);
|
||||
.def("return_vector2", &Test::return_vector2);
|
||||
;
|
||||
|
||||
class_<MyBase>("MyBase")
|
||||
.def("MyBase", &MyBase::MyBase);
|
||||
;
|
||||
|
||||
class_<MyTemplatePoint2>("MyTemplatePoint2")
|
||||
.def("MyTemplatePoint2", &MyTemplatePoint2::MyTemplatePoint2);
|
||||
.def("accept_T", &MyTemplatePoint2::accept_T);
|
||||
.def("accept_Tptr", &MyTemplatePoint2::accept_Tptr);
|
||||
.def("create_MixedPtrs", &MyTemplatePoint2::create_MixedPtrs);
|
||||
.def("create_ptrs", &MyTemplatePoint2::create_ptrs);
|
||||
.def("return_T", &MyTemplatePoint2::return_T);
|
||||
.def("return_Tptr", &MyTemplatePoint2::return_Tptr);
|
||||
.def("return_ptrs", &MyTemplatePoint2::return_ptrs);
|
||||
.def("templatedMethod", &MyTemplatePoint2::templatedMethod);
|
||||
.def("templatedMethod", &MyTemplatePoint2::templatedMethod);
|
||||
;
|
||||
|
||||
class_<MyTemplatePoint3>("MyTemplatePoint3")
|
||||
.def("MyTemplatePoint3", &MyTemplatePoint3::MyTemplatePoint3);
|
||||
.def("accept_T", &MyTemplatePoint3::accept_T);
|
||||
.def("accept_Tptr", &MyTemplatePoint3::accept_Tptr);
|
||||
.def("create_MixedPtrs", &MyTemplatePoint3::create_MixedPtrs);
|
||||
.def("create_ptrs", &MyTemplatePoint3::create_ptrs);
|
||||
.def("return_T", &MyTemplatePoint3::return_T);
|
||||
.def("return_Tptr", &MyTemplatePoint3::return_Tptr);
|
||||
.def("return_ptrs", &MyTemplatePoint3::return_ptrs);
|
||||
.def("templatedMethod", &MyTemplatePoint3::templatedMethod);
|
||||
.def("templatedMethod", &MyTemplatePoint3::templatedMethod);
|
||||
;
|
||||
|
||||
class_<MyFactorPosePoint2>("MyFactorPosePoint2")
|
||||
.def("MyFactorPosePoint2", &MyFactorPosePoint2::MyFactorPosePoint2);
|
||||
;
|
||||
|
||||
def("aGlobalFunction", aGlobalFunction);
|
||||
def("overloadedGlobalFunction", overloadedGlobalFunction);
|
||||
}
|
|
@ -32,12 +32,13 @@ TEST( Method, Constructor ) {
|
|||
/* ************************************************************************* */
|
||||
// addOverload
|
||||
TEST( Method, addOverload ) {
|
||||
Method method("myName");
|
||||
bool verbose = true, is_const = true;
|
||||
Method method;
|
||||
method.initializeOrCheck("myName");
|
||||
bool is_const = true;
|
||||
ArgumentList args;
|
||||
const ReturnValue retVal(ReturnType("return_type"));
|
||||
method.addOverload(verbose, is_const, "myName", args, retVal);
|
||||
EXPECT_LONGS_EQUAL(1,method.nrOverloads());
|
||||
method.addOverload("myName", args, retVal, is_const);
|
||||
EXPECT_LONGS_EQUAL(1, method.nrOverloads());
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
|
|
@ -64,12 +64,11 @@ TEST( wrap, check_exception ) {
|
|||
THROWS_EXCEPTION(Module("/notarealpath", "geometry",enable_verbose));
|
||||
CHECK_EXCEPTION(Module("/alsonotarealpath", "geometry",enable_verbose), CantOpenFile);
|
||||
|
||||
// clean out previous generated code
|
||||
fs::remove_all("actual_deps");
|
||||
|
||||
string path = topdir + "/wrap/tests";
|
||||
Module module(path.c_str(), "testDependencies",enable_verbose);
|
||||
CHECK_EXCEPTION(module.matlab_code("actual_deps", headerPath), DependencyMissing);
|
||||
// // TODO: matlab_code does not throw this anymore, so check constructor
|
||||
// fs::remove_all("actual_deps"); // clean out previous generated code
|
||||
// string path = topdir + "/wrap/tests";
|
||||
// Module module(path.c_str(), "testDependencies",enable_verbose);
|
||||
// CHECK_EXCEPTION(module.matlab_code("actual_deps"), DependencyMissing);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
@ -413,7 +412,7 @@ TEST( wrap, matlab_code_namespaces ) {
|
|||
// emit MATLAB code
|
||||
string exp_path = path + "/tests/expected_namespaces/";
|
||||
string act_path = "actual_namespaces/";
|
||||
module.matlab_code("actual_namespaces", headerPath);
|
||||
module.matlab_code("actual_namespaces");
|
||||
|
||||
|
||||
EXPECT(files_equal(exp_path + "ClassD.m", act_path + "ClassD.m" ));
|
||||
|
@ -441,7 +440,7 @@ TEST( wrap, matlab_code_geometry ) {
|
|||
|
||||
// emit MATLAB code
|
||||
// make_geometry will not compile, use make testwrap to generate real make
|
||||
module.matlab_code("actual", headerPath);
|
||||
module.matlab_code("actual");
|
||||
#ifndef WRAP_DISABLE_SERIALIZE
|
||||
string epath = path + "/tests/expected/";
|
||||
#else
|
||||
|
@ -461,6 +460,25 @@ TEST( wrap, matlab_code_geometry ) {
|
|||
EXPECT(files_equal(epath + "overloadedGlobalFunction.m" , apath + "overloadedGlobalFunction.m" ));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
TEST( wrap, python_code_geometry ) {
|
||||
// Parse into class object
|
||||
string header_path = topdir + "/wrap/tests";
|
||||
Module module(header_path,"geometry",enable_verbose);
|
||||
string path = topdir + "/wrap";
|
||||
|
||||
// clean out previous generated code
|
||||
fs::remove_all("actual-python");
|
||||
|
||||
// emit MATLAB code
|
||||
// make_geometry will not compile, use make testwrap to generate real make
|
||||
module.python_wrapper("actual-python");
|
||||
string epath = path + "/tests/expected-python/";
|
||||
string apath = "actual-python/";
|
||||
|
||||
EXPECT(files_equal(epath + "geometry_python.cpp", apath + "geometry_python.cpp" ));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
int main() { TestResult tr; return TestRegistry::runAllTests(tr); }
|
||||
/* ************************************************************************* */
|
||||
|
|
Loading…
Reference in New Issue