gpt4 book ai didi

Python 函数作为 C++ 中的参数

转载 作者:行者123 更新时间:2023-11-28 06:35:41 24 4
gpt4 key购买 nike

我正在尝试使用 Boost.Python 在 python 中公开 eigen3。

我找不到公开 function 的方法unaryExpr (const CustomUnaryOp &func=CustomUnaryOp())

我想要的是能让我做类似事情的东西:

python

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) 我尝试使用一个简单的回调定义

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

但 boost 不会将 python 函数转换为 UnaryExprType。

2) 我试着 implement a struct PythonCallBack,然而,它不起作用,我得到一个错误,python 签名与 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))

最佳答案

Boost.Python 旨在最大限度地减少与 PyObject 交互的需要,并且通常可以像使用它们一样简单地使用 boost::python::object使用 Python 中的对象。例如,如果 funcboost::python::object指的是 lambda x: 1,下面是带有注释 Python 注释的 Boost.Python 用法:

// >>> 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++ 代码可能期望仿函数的返回值是 C++ 类型而不是通用的 boost::python::object,因此可以使用包装器类型来调整仿函数。

/// @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_;
};

这是一个完整的最小示例:

#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)

关于Python 函数作为 C++ 中的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26820738/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com