У меня есть следующий код, который реализует простой класс С++ (ObjWithPyCallback) с функцией обратного вызова Python. Идея состоит в том, чтобы вызвать функцию Python с помощью "this" в качестве единственного аргумента.
Проблема в том, что поскольку ObjWithPyCallback - это обернутый SWIG-объект, мне нужен тип SWIG для создания объекта Python.
Проблема заключается в том, что он находится внутри созданного SWIG файла "ObjWithPyCallback_wrap.cxx". Может ли SWIG генерировать заголовочный файл? Я до сих пор не смог это сделать.
Однако даже с файлом заголовка существует циклическая зависимость между SWIG и моей основной реализацией, что раздражает. Я бы хотел найти способ избежать этого, если это вообще возможно. В конечном итоге ObjWithPyCallback заканчивается в другой общей библиотеке, чем привязки Python.
Есть ли чистый способ снять это? Я знаю этот пост, но он касается только механики 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"