2012-07-23 22:09:40 +08:00
|
|
|
/**
|
|
|
|
* @file GlobalFunction.cpp
|
|
|
|
*
|
|
|
|
* @date Jul 22, 2012
|
|
|
|
* @author Alex Cunningham
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "GlobalFunction.h"
|
2016-12-16 13:23:45 +08:00
|
|
|
#include "Class.h"
|
2012-07-24 02:24:35 +08:00
|
|
|
#include "utilities.h"
|
|
|
|
|
|
|
|
#include <boost/lexical_cast.hpp>
|
2012-07-23 22:09:40 +08:00
|
|
|
|
|
|
|
namespace wrap {
|
|
|
|
|
2012-07-24 02:24:35 +08:00
|
|
|
using namespace std;
|
|
|
|
|
2012-07-23 22:09:40 +08:00
|
|
|
/* ************************************************************************* */
|
2014-11-14 23:43:53 +08:00
|
|
|
void GlobalFunction::addOverload(const Qualified& overload,
|
2016-11-23 06:09:35 +08:00
|
|
|
const ArgumentList& args, const ReturnValue& retVal, const std::string& _includeFile,
|
2014-12-01 16:48:56 +08:00
|
|
|
boost::optional<const Qualified> instName, bool verbose) {
|
2014-12-01 03:12:03 +08:00
|
|
|
FullyOverloadedFunction::addOverload(overload.name(), args, retVal, instName,
|
|
|
|
verbose);
|
2014-11-12 09:49:23 +08:00
|
|
|
overloads.push_back(overload);
|
2016-11-23 06:09:35 +08:00
|
|
|
includeFile = _includeFile;
|
2012-07-23 22:09:40 +08:00
|
|
|
}
|
|
|
|
|
2012-07-24 02:24:35 +08:00
|
|
|
/* ************************************************************************* */
|
2014-11-14 23:43:53 +08:00
|
|
|
void GlobalFunction::matlab_proxy(const string& toolboxPath,
|
|
|
|
const string& wrapperName, const TypeAttributesTable& typeAttributes,
|
|
|
|
FileWriter& file, vector<string>& functionNames) const {
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// cluster overloads with same namespace
|
|
|
|
// create new GlobalFunction structures around namespaces - same namespaces and names are overloads
|
|
|
|
// map of namespace to global function
|
|
|
|
typedef map<string, GlobalFunction> GlobalFunctionMap;
|
|
|
|
GlobalFunctionMap grouped_functions;
|
2014-11-12 09:49:23 +08:00
|
|
|
for (size_t i = 0; i < overloads.size(); ++i) {
|
|
|
|
Qualified overload = overloads.at(i);
|
|
|
|
// use concatenated namespaces as key
|
2014-12-01 03:12:03 +08:00
|
|
|
string str_ns = qualifiedName("", overload.namespaces());
|
2014-11-14 00:28:05 +08:00
|
|
|
const ReturnValue& ret = returnValue(i);
|
|
|
|
const ArgumentList& args = argumentList(i);
|
2014-11-14 23:43:53 +08:00
|
|
|
grouped_functions[str_ns].addOverload(overload, args, ret);
|
2012-10-02 22:40:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t lastcheck = grouped_functions.size();
|
2016-05-21 09:41:18 +08:00
|
|
|
for(const GlobalFunctionMap::value_type& p: grouped_functions) {
|
2014-05-26 04:01:30 +08:00
|
|
|
p.second.generateSingleFunction(toolboxPath, wrapperName, typeAttributes,
|
|
|
|
file, functionNames);
|
2012-10-02 22:40:07 +08:00
|
|
|
if (--lastcheck != 0)
|
2014-05-26 04:01:30 +08:00
|
|
|
file.oss << endl;
|
2012-10-02 22:40:07 +08:00
|
|
|
}
|
2012-07-24 02:24:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2014-11-14 23:43:53 +08:00
|
|
|
void GlobalFunction::generateSingleFunction(const string& toolboxPath,
|
|
|
|
const string& wrapperName, const TypeAttributesTable& typeAttributes,
|
|
|
|
FileWriter& file, vector<string>& functionNames) const {
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// create the folder for the namespace
|
2014-11-12 09:49:23 +08:00
|
|
|
const Qualified& overload1 = overloads.front();
|
2014-12-01 03:12:03 +08:00
|
|
|
createNamespaceStructure(overload1.namespaces(), toolboxPath);
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// open destination mfunctionFileName
|
2014-11-12 09:49:23 +08:00
|
|
|
string mfunctionFileName = overload1.matlabName(toolboxPath);
|
2012-10-02 22:40:07 +08:00
|
|
|
FileWriter mfunctionFile(mfunctionFileName, verbose_, "%");
|
|
|
|
|
|
|
|
// get the name of actual matlab object
|
2014-11-12 09:49:23 +08:00
|
|
|
const string matlabQualName = overload1.qualifiedName(".");
|
|
|
|
const string matlabUniqueName = overload1.qualifiedName("");
|
|
|
|
const string cppName = overload1.qualifiedName("::");
|
2012-10-02 22:40:07 +08:00
|
|
|
|
2014-11-13 19:52:41 +08:00
|
|
|
mfunctionFile.oss << "function varargout = " << name_ << "(varargin)\n";
|
2012-10-02 22:40:07 +08:00
|
|
|
|
2014-11-14 00:28:05 +08:00
|
|
|
for (size_t i = 0; i < nrOverloads(); ++i) {
|
|
|
|
const ArgumentList& args = argumentList(i);
|
|
|
|
const ReturnValue& returnVal = returnValue(i);
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
const int id = functionNames.size();
|
|
|
|
|
|
|
|
// Output proxy matlab code
|
2014-11-14 00:28:05 +08:00
|
|
|
mfunctionFile.oss << " " << (i == 0 ? "" : "else");
|
2014-11-30 03:59:38 +08:00
|
|
|
emit_conditional_call(mfunctionFile, returnVal, args, wrapperName, id);
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// Output C++ wrapper code
|
|
|
|
|
2014-05-26 04:01:30 +08:00
|
|
|
const string wrapFunctionName = matlabUniqueName + "_"
|
|
|
|
+ boost::lexical_cast<string>(id);
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// call
|
2014-05-26 04:01:30 +08:00
|
|
|
file.oss << "void " << wrapFunctionName
|
|
|
|
<< "(int nargout, mxArray *out[], int nargin, const mxArray *in[])\n";
|
2012-10-02 22:40:07 +08:00
|
|
|
// start
|
2014-05-26 04:01:30 +08:00
|
|
|
file.oss << "{\n";
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// check arguments
|
|
|
|
// NOTE: for static functions, there is no object passed
|
2014-05-26 04:01:30 +08:00
|
|
|
file.oss << " checkArguments(\"" << matlabUniqueName
|
|
|
|
<< "\",nargout,nargin," << args.size() << ");\n";
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// unwrap arguments, see Argument.cpp
|
2014-05-26 04:01:30 +08:00
|
|
|
args.matlab_unwrap(file, 0); // We start at 0 because there is no self object
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// call method with default type and wrap result
|
2014-12-01 03:12:03 +08:00
|
|
|
if (returnVal.type1.name() != "void")
|
2014-05-26 04:01:30 +08:00
|
|
|
returnVal.wrap_result(cppName + "(" + args.names() + ")", file,
|
|
|
|
typeAttributes);
|
2012-10-02 22:40:07 +08:00
|
|
|
else
|
2014-05-26 04:01:30 +08:00
|
|
|
file.oss << cppName + "(" + args.names() + ");\n";
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// finish
|
2014-05-26 04:01:30 +08:00
|
|
|
file.oss << "}\n";
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// Add to function list
|
|
|
|
functionNames.push_back(wrapFunctionName);
|
|
|
|
}
|
|
|
|
|
2014-05-26 04:28:39 +08:00
|
|
|
mfunctionFile.oss << " else\n";
|
2014-05-26 04:01:30 +08:00
|
|
|
mfunctionFile.oss
|
2014-05-26 04:28:39 +08:00
|
|
|
<< " error('Arguments do not match any overload of function "
|
2014-05-26 04:01:30 +08:00
|
|
|
<< matlabQualName << "');" << endl;
|
2014-05-26 04:28:39 +08:00
|
|
|
mfunctionFile.oss << " end" << endl;
|
2012-10-02 22:40:07 +08:00
|
|
|
|
|
|
|
// Close file
|
|
|
|
mfunctionFile.emit(true);
|
2012-07-24 02:24:35 +08:00
|
|
|
}
|
|
|
|
|
2014-11-15 00:47:25 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
void GlobalFunction::python_wrapper(FileWriter& wrapperFile) const {
|
|
|
|
wrapperFile.oss << "def(\"" << name_ << "\", " << name_ << ");\n";
|
|
|
|
}
|
|
|
|
|
2016-11-23 06:09:35 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
void GlobalFunction::emit_cython_pxd(FileWriter& file) const {
|
|
|
|
file.oss << "cdef extern from \"" << includeFile << "\" namespace \""
|
|
|
|
<< overloads[0].qualifiedNamespaces("::")
|
|
|
|
<< "\":" << endl;
|
|
|
|
for (size_t i = 0; i < nrOverloads(); ++i) {
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " ";
|
2016-12-16 13:23:45 +08:00
|
|
|
returnVals_[i].emit_cython_pxd(file, "", vector<string>());
|
|
|
|
file.oss << pxdName() + " \"" + overloads[0].qualifiedName("::") +
|
2016-11-23 06:09:35 +08:00
|
|
|
"\"(";
|
2016-12-16 13:23:45 +08:00
|
|
|
argumentList(i).emit_cython_pxd(file, "", vector<string>());
|
2016-11-23 06:09:35 +08:00
|
|
|
file.oss << ")";
|
|
|
|
file.oss << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ************************************************************************* */
|
2016-11-23 06:32:48 +08:00
|
|
|
void GlobalFunction::emit_cython_pyx_no_overload(FileWriter& file) const {
|
2016-12-16 13:23:45 +08:00
|
|
|
string funcName = pyxName();
|
2016-11-23 06:09:35 +08:00
|
|
|
|
|
|
|
// Function definition
|
|
|
|
file.oss << "def " << funcName;
|
2017-08-07 02:07:13 +08:00
|
|
|
|
2016-11-23 06:09:35 +08:00
|
|
|
// modify name of function instantiation as python doesn't allow overloads
|
|
|
|
// e.g. template<T={A,B,C}> funcName(...) --> funcNameA, funcNameB, funcNameC
|
2016-11-25 08:22:44 +08:00
|
|
|
if (templateArgValue_) file.oss << templateArgValue_->pyxClassName();
|
2017-08-07 02:07:13 +08:00
|
|
|
|
2016-11-23 06:09:35 +08:00
|
|
|
// funtion arguments
|
|
|
|
file.oss << "(";
|
|
|
|
argumentList(0).emit_cython_pyx(file);
|
|
|
|
file.oss << "):\n";
|
|
|
|
|
|
|
|
/// Call cython corresponding function and return
|
convert numpy input params to dtype float and order 'F' automatically
using numpy.astype(...). No copy if the params are already in the correct dtype and storage order.
For a function
f(Matrix A, Matrix B),
simply wrapping it to pyx as
f(A.astype(float, order='F', copy=False), B.astype(float, order='F', copy=False))
won't work.
It produces a strange side-effect that the content of A is overwritten by B and the two inputs are the same (data address) inside the function!
This is because Cython decreases the ref count for the temporary variable resulted from A.astype(...) before generates the wrap for B.astype(...).
Hence, the A.astype temp var is probably reused for B.astype, and they were pointing to the same data address.
For that reason, we have to go a longer route and wrap it as:
A = A.astype(float, order='F', copy=False)
B = B.astype(float, order='F', copy=False)
f(A, B)
For future ref., here is a sample of the wrongly generated code that wraps the JacobianFactor constructor:
Jacobian(Key i1, Matrix A1, Key i2, Matrix A2, Vector b, noiseModel::Diagonal model)
Wrongly wrapped pyx code:
self.shared_CJacobianFactor_ = shared_ptr[CJacobianFactor](new CJacobianFactor(i1, <MatrixXd>(Map[MatrixXd](A1.astype(float, order='F',copy=False)), i2, <MatrixXd>(Map[MatrixXd](A2.astype(float, order='F', copy=False)), <VectorXd>(Map[VectorXd](b.astype(float, order='F', copy=False))), model.shared_CnoiseModel_Diagonal_))
The problematic Cython generated CPP code with a comment on the problematic line:
/////////////////////////////////////////
// WRONG VERSION
/////////////////////////////////////////
__pyx_t_12 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_A1), __pyx_n_s_astype); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_14 = eigency::Map<Eigen::MatrixXd> (((PyArrayObject *)__pyx_t_13));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
///////////////////////////////////////////////
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0; //<------- Problematic line!!! Killing this will result in the correct result!
///////////////////////////////////////////////
__pyx_t_13 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_A2), __pyx_n_s_astype); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__pyx_t_5 = PyTuple_New(1); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_5, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_4 = PyDict_New(); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_12 = __Pyx_PyObject_Call(__pyx_t_13, __pyx_t_5, __pyx_t_4); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
if (!(likely(((__pyx_t_12) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_12, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_15 = eigency::Map<Eigen::MatrixXd> (((PyArrayObject *)__pyx_t_12));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__pyx_t_12 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_b), __pyx_n_s_astype); if (unlikely(!__pyx_t_12)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_12);
__pyx_t_4 = PyTuple_New(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_4);
__Pyx_INCREF(((PyObject *)(&PyFloat_Type)));
__Pyx_GIVEREF(((PyObject *)(&PyFloat_Type)));
PyTuple_SET_ITEM(__pyx_t_4, 0, ((PyObject *)(&PyFloat_Type)));
__pyx_t_5 = PyDict_New(); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_5);
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_order, __pyx_n_s_F) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
if (PyDict_SetItem(__pyx_t_5, __pyx_n_s_copy, Py_False) < 0) __PYX_ERR(0, 2107, __pyx_L1_error)
__pyx_t_13 = __Pyx_PyObject_Call(__pyx_t_12, __pyx_t_4, __pyx_t_5); if (unlikely(!__pyx_t_13)) __PYX_ERR(0, 2107, __pyx_L1_error)
__Pyx_GOTREF(__pyx_t_13);
__Pyx_DECREF(__pyx_t_12); __pyx_t_12 = 0;
__Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
__Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
if (!(likely(((__pyx_t_13) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_13, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 2107, __pyx_L1_error)
try {
__pyx_t_16 = eigency::Map<Eigen::VectorXd> (((PyArrayObject *)__pyx_t_13));
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__Pyx_DECREF(__pyx_t_13); __pyx_t_13 = 0;
try {
__pyx_t_17 = new gtsam::JacobianFactor(__pyx_v_i1, ((Eigen::MatrixXd)__pyx_t_14), __pyx_v_i2, ((Eigen::MatrixXd)__pyx_t_15), ((Eigen::VectorXd)__pyx_t_16), __pyx_v_model->shared_CnoiseModel_Diagonal_);
} catch(...) {
__Pyx_CppExn2PyErr();
__PYX_ERR(0, 2107, __pyx_L1_error)
}
__pyx_v_self->shared_CJacobianFactor_ = boost::shared_ptr<gtsam::JacobianFactor> (__pyx_t_17);
2017-03-16 01:47:11 +08:00
|
|
|
file.oss << argumentList(0).pyx_convertEigenTypeAndStorageOrder(" ");
|
2016-12-16 13:23:45 +08:00
|
|
|
string ret = pyx_functionCall("", pxdName(), 0);
|
2016-11-23 06:09:35 +08:00
|
|
|
if (!returnVals_[0].isVoid()) {
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " cdef " << returnVals_[0].pyx_returnType()
|
2016-11-23 06:09:35 +08:00
|
|
|
<< " ret = " << ret << "\n";
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " return " << returnVals_[0].pyx_casting("ret") << "\n";
|
2016-11-23 06:09:35 +08:00
|
|
|
} else {
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " " << ret << "\n";
|
2016-11-23 06:09:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-23 06:32:48 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
void GlobalFunction::emit_cython_pyx(FileWriter& file) const {
|
2016-12-16 13:23:45 +08:00
|
|
|
string funcName = pyxName();
|
2016-11-23 06:32:48 +08:00
|
|
|
|
|
|
|
size_t N = nrOverloads();
|
|
|
|
if (N == 1) {
|
|
|
|
emit_cython_pyx_no_overload(file);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dealing with overloads..
|
|
|
|
file.oss << "def " << funcName << "(*args, **kwargs):\n";
|
|
|
|
for (size_t i = 0; i < N; ++i) {
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " success, results = " << funcName << "_" << i
|
2017-08-07 02:07:13 +08:00
|
|
|
<< "(args, kwargs)\n";
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " if success:\n return results\n";
|
2016-11-23 06:32:48 +08:00
|
|
|
}
|
2016-11-30 18:56:07 +08:00
|
|
|
file.oss << " raise TypeError('Could not find the correct overload')\n";
|
2016-11-23 06:32:48 +08:00
|
|
|
|
|
|
|
for (size_t i = 0; i < N; ++i) {
|
|
|
|
ArgumentList args = argumentList(i);
|
2017-08-07 02:07:13 +08:00
|
|
|
file.oss << "def " + funcName + "_" + to_string(i) + "(args, kwargs):\n";
|
|
|
|
file.oss << " cdef list __params\n";
|
|
|
|
if (!returnVals_[i].isVoid()) {
|
|
|
|
file.oss << " cdef " << returnVals_[i].pyx_returnType() << " return_value\n";
|
|
|
|
}
|
|
|
|
file.oss << " try:\n";
|
|
|
|
file.oss << pyx_resolveOverloadParams(args, false, 2); // lazy: always return None even if it's a void function
|
2016-11-23 06:32:48 +08:00
|
|
|
|
2017-08-07 02:07:13 +08:00
|
|
|
/// Call corresponding cython function
|
|
|
|
file.oss << argumentList(i).pyx_convertEigenTypeAndStorageOrder(" ");
|
|
|
|
string call = pyx_functionCall("", pxdName(), i);
|
2016-11-23 06:32:48 +08:00
|
|
|
if (!returnVals_[i].isVoid()) {
|
2017-08-07 02:07:13 +08:00
|
|
|
file.oss << " return_value = " << call << "\n";
|
|
|
|
file.oss << " return True, " << returnVals_[i].pyx_casting("return_value") << "\n";
|
2016-11-23 06:32:48 +08:00
|
|
|
} else {
|
2017-08-07 02:07:13 +08:00
|
|
|
file.oss << " " << call << "\n";
|
|
|
|
file.oss << " return True, None\n";
|
2016-11-23 06:32:48 +08:00
|
|
|
}
|
2017-08-07 02:07:13 +08:00
|
|
|
file.oss << " except:\n";
|
|
|
|
file.oss << " return False, None\n\n";
|
2016-11-23 06:32:48 +08:00
|
|
|
}
|
|
|
|
}
|
2012-07-23 22:09:40 +08:00
|
|
|
/* ************************************************************************* */
|
|
|
|
|
|
|
|
} // \namespace wrap
|
|
|
|
|