2014-11-08 7 views
0

Boost.Python을 사용하여 파이썬에서 eigen3을 노출하려고합니다.C++의 인수로 파이썬 함수

내가하고 싶은 무엇 functionunaryExpr (const CustomUnaryOp &func=CustomUnaryOp())

를 노출 할 수있는 방법을 찾을 수없는 것은 그런 일에 저를 허용 뭔가 :

파이썬

import libMatrix as mat 
a = mat.Matrix(10, 10) 
mat.unary_expr(lambda x : 1) 

당신이 어떤이 있습니까 아이디어 ?? 다음과 같이 보일 수 있습니다.

void unary_expr(Matrix const& self, PyObject* callable_object) 
{ 
    cpp_callable = ??(callable_object) 
    self.unaryEpxr(cpp_callable); 
} 

=== 내가 시도한 것 : ============== ============

1) 나는 UnaryExprType에 파이썬 기능을 변환하지 않습니다 간단한 콜백 정의

typedef double(*UnaryExprType)(double); 
void unary_expr(Matrix const& self, UnaryExprType a); 
    { 
     self.unaryEpxr(a); 
    } 

하지만 부스트를 사용했습니다.

2) 나는 implement a structPythonCallBack을 시도했지만, 작동하지 않습니다. 파이썬 서명이 C++ 서명과 일치하지 않는다는 오류가 있습니다.

struct PythonCallBackBase 
{ 
public: 
    virtual ~PythonCallBackBase() {} 
    virtual double operator() (double const & x) { return 0; } 
}; 

struct PythonCallBack : PythonCallBackBase, boost::python::wrapper<PythonCallBackBase> 
{ 
public: 
    typedef boost::python::wrapper<PythonCallBackBase> wrap; 

    double default_op(double const & x) 
    { 
     return 0; 
    } 

    double operator() (double const & x) 
    { 
     if (boost::python::override f = wrap::get_override("__call__")) 
      return f(x); 
     return PythonCallBackBase::operator()(x); 
    } 
}; 

void unary_expr(Matrix const& self, PythonCallBack a) 
{ 
    self.unaryEpxr(a); 
} 

오류 메시지

ArgumentError: Python argument types in 
    Matrix.unary_expr(Matrix, Boost.Python.class) 
did not match C++ signature: 
    unary_expr(Eigen::Matrix<double, -1, -1, 0, -1, -1>, PythonCallBack) 
    unary_expr(Eigen::Matrix<double, -1, -1, 0, -1, -1>, double (*)(double)) 
+0

불가능한 것 같다 여기

/// @brief Auxiliary type that adapts a Boost.Python object to a /// unary functor with an explicit return type. template <typename Arg, typename Result> class py_unary_functor { public: typedef Arg argument_type; typedef Result result_type; py_unary_functor(boost::python::object object) : object_(object) {} result_type operator()(argument_type a1) { return boost::python::extract<result_type>(object_(a1))(); } private: boost::python::object object_; }; 

는 완전한 최소한의 예입니다. http://www.boost.org/doc/libs/1_52_0/libs/python/doc/v2/faq.html – Setepenre

답변

1

Boost.Python은 PyObject와 상호 작용하는 필요성을 최소화하도록 설계하고, 하나는 파이썬의 객체와 동일한 방식으로 그들이하고자에서 사용 boost::python::object 간단한 종종 있습니다. 가능성이 펑터의 복귀를 기대하고이 경우

// >>> func = lambda x: 1 
boost::python::object func = ...; 
// >>> result = func(42) 
boost::python::object result = func(42); 
// >>> assert(1 == result) 
assert(1 == boost::python::extract<int>(result)); 

의 C++ 코드로 : 예를 들어, func 경우 lambda x: 1을 참조하는 boost::python::object이며, 여기에 주석 파이썬 주석이있는 다음 Boost.Python 사용입니다 값이 일반 boost::python::object이 아닌 C++ 유형이되도록하려면 래퍼 유형을 사용하여 함수 작성자를 적용 할 수 있습니다.

#include <boost/python.hpp> 

/// @brief Mockup matrix class. 
struct matrix 
{ 
    template <typename CustomUnaryOp> 
    void unaryExpr(CustomUnaryOp func) 
    { 
    value = func(value); 
    } 

    double value; 
}; 

/// @brief Auxiliary type that adapts a Boost.Python object to a 
///  unary functor with an explicit return type. 
template <typename Arg, typename Result> 
class py_unary_functor 
{ 
public: 

    typedef Arg argument_type; 
    typedef Result result_type; 

    py_unary_functor(boost::python::object object) 
    : object_(object) 
    {} 

    result_type operator()(argument_type a1) 
    { 
    return boost::python::extract<result_type>(object_(a1))(); 
    } 

private: 
    boost::python::object object_; 
}; 

/// @brief Auxiliary function used to adapt matrix::unaryExpr. 
void matrix_unaryExpr(
    matrix& self, 
    boost::python::object object) 
{ 
    py_unary_functor<double, double> func(object); 
    return self.unaryExpr(func); 
} 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 
    python::class_<matrix>("Matrix") 
    // Expose auxiliary function. 
    .def("unaryExpr", &matrix_unaryExpr) 
    .add_property("value", &matrix::value, &matrix::value) 
    ; 
} 

대화 형 사용 :

>>> import example 
>>> matrix = example.Matrix() 
>>> matrix.value = 21 
>>> assert(21 == matrix.value) 
>>> matrix.unaryExpr(lambda x: x*2) 
>>> assert(42 == matrix.value)