我有下面的代码,它实现了一个简单的C++类(ObjutpyPrCuBube),带有Python回调函数。其思想是用“this”作为单个参数来调用Python函数。
问题是,由于ObjWithPyCallback是一个SWIG包装的对象,我需要SWIG typeinfo来创建一个Python对象。
问题是它在SWIG生成的文件“ObjWithPyCallback_wrap.cxx”中。SWIG可以生成头文件吗?到目前为止,我还没能做到这一点。
但是,即使有头文件,SWIG和我的主实现之间也存在循环依赖关系,这很烦人。如果可能的话,我想找个办法避免它。最终,ObjWithPyCallback会出现在与Python绑定不同的共享库中。
有没有一个干净的方法来完成这个?我知道this post,但它只涉及SWIG廑NewPointerObj的机制。
提前感谢您的帮助!
代码如下:
文件:example.py
import cb
def foo(x=None):
print("Hello from Foo!")
# I'd like x to be a reference to a ObjWithPyCallback object.
print(x)
o = cb.ObjWithPyCallback()
o.setCallback(foo)
o.call()
文件:ObjWithPyCallback.h
#include <Python.h>
class ObjWithPyCallback
{
public:
ObjWithPyCallback();
void setCallback(PyObject *callback);
void call();
PyObject *callback_;
};
文件:ObjWithCallback.cpp
#include "ObjWithPyCallback.h"
#include <iostream>
ObjWithPyCallback::ObjWithPyCallback() : callback_(NULL) {}
void ObjWithPyCallback::setCallback(PyObject* callback)
{
if (!PyCallable_Check(callback))
{
std::cerr << "Object is not callable.\n";
}
else
{
if ( callback_ ) Py_XDECREF(callback_);
callback_ = callback;
Py_XINCREF(callback_);
}
}
void ObjWithPyCallback::call()
{
if ( ! callback_ )
{
std::cerr << "No callback is set.\n";
}
else
{
// I want to call "callback_(*this)", how to do this cleanly?
PyObject *result = PyObject_CallFunction(callback_, "");
if (result == NULL)
std::cerr << "Callback call failed.\n";
else
Py_DECREF(result);
}
}
文件::ObjWithPyCallback.i
%module cb
%{
#include "ObjWithPyCallback.h"
%}
%include "ObjWithPyCallback.h"
一。解决问题的总体思路:
(1) 是的。定义一个名为回调的C++类,它具有方法Run()
(2) 是的。在Python代码中继承回调,并创建一个实例。
(3) 是的。使用C++方法将实例绑定到C++点子。
(4) 是的。使用指针访问在python代码中定义的run()。
2。示例代码
(1) 是的。示例.h
(2) 是的。示例.cxx
(3) 是的。示例i
三。编译
四。在python shell中使用
5个。其他
我想你还需要更多的东西。尝试:
我将使用SWIG处理继承的机制,并拥有一个带有虚拟函数
在Python中,您只需确定设置回调的位置,就将其包在由C++回调类派生的Python类的实例中,并使其^ {< CD2>}成员函数执行回调。这也是你做测试的地方,看看它是否可以调用。然后用这个包装器对象调用void call()
的回调类。然后使用SWIG使该类在Python中能够派生。setCallback
函数。下面是我解决这个问题的工作方案。它使用了上述“无所不能”和“柔印”的建议。
特别是,我们用SWIG director创建一个回调类,然后在Python中从中派生出所需的回调功能,而不引入循环依赖项。
此外,我们还提供了一个接口,允许任何可调用的Python对象充当回调函数。我们通过在SWIG中使用“pythonprend”指令为“setCallback”函数添加一些代码来实现这一点。这段代码只是检查一个可调用的对象,如果它找到了一个对象,则将其包装在回调的实例中。
最后,我们处理与C++类(ObjutPyCalBub)引用相关的内存问题,即引用对象(即回调子类)。文件example.py:
文件ObjWithPyCallback.i:
文件回调.h:
文件ObjWithPyCallback.h:
文件ObjWithPyCallback.cpp:
相关问题 更多 >
编程相关推荐