使用引用参数增强 Python 方法调用
boost python method calls with reference arguments
尝试通过引用从python到C++类方法进行简单的调用时:
class Foo {
protected:
int _internalVal;
public:
Foo() : _internalVal(5){}
void getVal(int& val_io) {val_io = _internalVal;}
void getValDoesNothing(int val_io) {val_io = _internalVal;}
}
可以编译 boost 包装器代码:
BOOST_PYTHON_MODULE(libBar) {
boost::python::class_<Foo>("Foo")
.def("getVal", &Foo::getVal)
.def("getValDoesNothing", &Foo::getValDoesNothing);
}
但是,在python中执行该功能时会发生错误:
In [1]: import libBar
In [2]: f = libBar.Foo()
In [3]: f
Out[3]: <libBar.Foo at 0x2b483c0>
In [4]: val = int()
In [5]: #next command is just to check function signature type
In [6]: f.getValDoesNothing(val)
In [7]: f.getVal(val)
---------------------------------------------------------------------------
ArgumentError Traceback (most recent call last)
<ipython-input-5-531e4cea97c2> in <module>()
----> 1 f.getVal(val)
ArgumentError: Python argument types in
Foo.getVal(Foo, int)
did not match C++ signature:
getVal(Foo {lvalue}, int {lvalue})
我正在使用一个我无法控制的C++库,因此更改 getVal 以返回值不是一个选项。
有没有办法让最后一个 Python 命令工作?
我什至会采取一个修复程序,它不会更改 Python 变量,但仍允许函数调用。
你试图实现的目标在 Python 中是无效的。整数是不可变的,所以你不能简单地调用一个函数,并希望它会改变它的内容。
由于您正在使用无法控制的库,并且更改 getVal 以返回值不是一个选项,因此您可以创建如下包装器:
int getVal(Foo &foo) {
int val_io;
foo.getVal(val_io);
return val_io;
};
BOOST_PYTHON_MODULE(libBar) {
boost::python::def("getVal", getVal);
...
}
然后以这种方式使用:
In [1]: import libBar
In [2]: f = libBar.Foo()
In [3]: f
Out[3]: <libBar.Foo at 0x2b483c0
In [3]: libBar.getVal(f)
Out[3]: 5
我使用带有单个元素的 numpy 数组来完成您正在尝试的操作。这是我在文件 ipc-messenger.h 中包装的类(在我的例子中,使用 MsgBuf 的 int 实现):
template <class MsgBuf>
class IPCMessenger {
public:
IPCMessenger(const char* name);
virtual ~IPCMessenger();
virtual int Notify(const MsgBuf& msg, unsigned int priority = 0);
int Receive(MsgBuf& msg, unsigned int* priority = nullptr);
int Terminate();
private:
boost::interprocess::message_queue _mq; /// boost IPC Message Queue.
std::string _queue_name; /// application defined queue name
};
这是 ipc-messenger_py.cpp 中的包装类
#include <boost/python.hpp>
#include "ipc-messenger.h"
#include <boost/python/numpy.hpp>
using namespace boost::python;
using namespace std;
namespace np = boost::python::numpy;
class IPCMessengerPy : public IPCMessenger<int> {
public:
IPCMessengerPy(const char* name) : IPCMessenger(name) {}
~IPCMessengerPy() {}
int Receive(np::ndarray & arr) {
int ret = 0;
int* p = (long *)arr.get_data();
return IPCMessenger::Receive(*p);
}
int Notify(np::ndarray& arr) {
int p = (long *)arr.get_data();
return IPCMessenger::Notify(*p);
}
};
BOOST_PYTHON_MODULE(ipcmessengerpy)
{
Py_Initialize();
np::initialize();
class_<IPCMessengerPy, boost::noncopyable>("ipcmessenger", init<const char*>())
.def( "receive", &IPCMessengerPy::Receive )
.def( "send", &IPCMessengerPy::Notify )
;
}
这可以从 python 调用,如下所示:
import ipcmessengerpy
import numpy as np
import time
# run this script in background, and then run ipc-master.py
q = ipcmessengerpy.ipcmessenger("QueueName")
buf = np.zeros([1], dtype = np.int32)
for c in range(0, 10):
q.receive(buf)
print "Received ", buf[0], " on q"
在getValDoesNothing中,你正在传递一个整数。在getVal中,你传递了一个对int的引用。
我相信这是你问题的根源。
相关文章:
- 如何通过python方法和kwargs来提升python的c++函数和调用
- 将FFMpeg AVFrame对象从C++应用程序流式传输到Python的最佳方法?
- 如何将 c++ 类包装到 python 中,以便我可以使用 pybind11 访问其成员的公共方法(成员是一个对象指针)
- 在 c++ 或 python 中生成一个体面的视差图以在 Raspberry Pi 上实现的最佳方法(算法或函数)是什么
- 无法将__str__特殊方法与Boost::Python接口
- 方法 argv[] SWIG C++ / Python 中的错误,会发生什么?
- 在C++和Python之间交换数据的最快方法是什么?
- Python的追加方法C++等价物是什么?
- 我如何在C++中使用某种方法来替换 python 中的 isdisjoint
- 如何使用Python脚本或其他一些方法来美化所有文件
- boost.python:如何获取super()方法
- 在 Python 中使用 C/C++ 的最快方法是什么?
- Python方法的OpenCV C 类似物
- 有没有一种方法可以从C++中调用"async"python方法
- 从Python方法中访问Python类中的C指针,Cython
- 使用引用参数增强 Python 方法调用
- 从 C++ 调用的 python 方法返回列表
- 从 C++ "库"调用 Python 方法
- 从c++(或C)回调调用python方法
- 将简单的python方法转换为c++