使用 swig 继承 c++ 时出错

error in inheritance c++ using swig

我有一个由 swig 包装并由 python 使用的 c++ 代码。 我想在 C++ 代码中创建一种 运行 回调 python 代码的方法。 所以我创建了一个 "abstract" class (它还不是抽象的)并且我在 .i 文件中用 c++ 将它分类。

这是我写的一些代码片段

.h 文件

class Listener {
public:
    Listener();
    virtual void register_new();
    virtual void run(Msg &m);
    virtual ~Listener();
};

.i 文件

%feature("director") PyListener;
using namespace std;
%{
#include "../core/listener.h"
%}

%include "../core/listener.h"

class PyListener : public Listener {
    PyObject * function;
public:
    PyListener() {};
    PyListener(PyObject * func) : function(func) {};
    void register_new() {Py_XINCREF(function);};
    ~PyListener () {Py_XDECREF(function);};
     void run(Msg &m) {
        PyGILState_STATE gstate;
        gstate = PyGILState_Ensure();
        PyObject *pValue = PyCObject_FromVoidPtr((void*)&m,NULL);
        PyObject *pArgs = PyTuple_New(1);
        PyTuple_SetItem(pArgs, 0, pValue);
        PyObject_CallObject(function, pArgs);
        PyGILState_Release(gstate);
    };
};

但在编译期间得到

/bin/sh ../../libtool --tag=CXX   --mode=compile g++ -DHAVE_CONFIG_H -I. -I../.. -I. -I./../core -I./../../../include -I/opt/regression/usr/include/ -I./../../include_dep/ -I/usr/include/python2.6  -fPIC    -g -O2 -MT sim_wrap.lo -MD -MP -MF .deps/sim_wrap.Tpo -c -o sim_wrap.lo sim_wrap.cxx
libtool: compile:  g++ -DHAVE_CONFIG_H -I. -I../.. -I. -I./../core -I./../../../include -I/opt/regression/usr/include/ -I./../../include_dep/ -I/usr/include/python2.6 -fPIC -g -O2 -MT sim_wrap.lo -MD -MP -MF .deps/sim_wrap.Tpo -c sim_wrap.cxx  -fPIC -DPIC -o .libs/sim_wrap.o
sim_wrap.cxx: In function ‘PyObject* _wrap_new_PyListener__SWIG_0(PyObject*, PyObject*)’:
sim_wrap.cxx:36391: error: ‘PyListener’ was not declared in this scope
sim_wrap.cxx:36391: error: ‘result’ was not declared in this scope
sim_wrap.cxx:36394: error: expected primary-expression before ‘)’ token
sim_wrap.cxx:36394: error: expected ‘;’ before ‘new’
...

由于您同时声明和定义了一个新的 class,因此您需要将其包含在 SWIG 界面的 %inline 中,例如

%inline %{
    class PyListener : public Listener {
        PyObject * function;
    public:
        PyListener() {};
        PyListener(PyObject * func) : function(func) {};
        void register_new() {Py_XINCREF(function);};
        ~PyListener () {Py_XDECREF(function);};
         void run(Msg &m) {
            PyGILState_STATE gstate;
            gstate = PyGILState_Ensure();
            PyObject *pValue = PyCObject_FromVoidPtr((void*)&m,NULL);
            PyObject *pArgs = PyTuple_New(1);
            PyTuple_SetItem(pArgs, 0, pValue);
            PyObject_CallObject(function, pArgs);
            PyGILState_Release(gstate);
        };
    };
%}

这会导致 SWIG 不仅包装类型,还会将 declaration/definition 传递给生成的 C++ 代码。这是必需的,因为 PyListener 特定于您的 SWIG 接口,因此在您的任何其他头文件中都不知道。