我们如何正确实现子类C ++对象的Python绑定?

时间:2010-07-16 19:31:03

标签: c++ python inheritance

我遇到了C ++和Python相当错综复杂的交互问题,我希望社区可以帮助我。如果我的解释没有意义,请在评论中告诉我,我会尽力澄清。

我们的C ++代码库包含一个名为“IODevice”的父类,它是其他类的父类,如“File”和“Socket”等等。我们已经这样做了,因此在我们的大部分代码中,我们可以使用“IODevice”对象,这些对象实际上可能是文件或套接字或我们最初构造的任何内容。这一切都在C ++代码中正常工作。

我们已经开始为我们的一些对象构建Python绑定。我们不想修改原来的“文件”或“套接字”类;我们创建了“File”和“Socket”类的“FilePy”和“SocketPy”子类。这些* Py类包含必要的Python绑定代码。

这是问题的起点。假设我有一个“InputProcessorPy”C ++类,它具有适当的Python绑定。我希望能够在我的Python代码中构造它并传递一个“FilePy”或“SocketPy”对象,“InputProcessorPy”将从中提取数据。 “InputProcessorPy”中的Python绑定代码如下所示:

PyObject* InputProcessor::PyMake(PyObject* ignored, PyObject *args)
{
    PyObject* cD_py;
    IODevice* inputFile;

    if (!PyArg_ParseTuple(args, "O", &cD_py))
        return NULL;

    inputFile = (IODevice*) cD_py;
    inputFile->isReadable();
    printf("------>>>> Done\n");

    return (PyObject *) new CL_InputRenderer(*inputFile, InputProcessor::Type);
}

如果我运行此代码,当我调用inputFile的isReadable()方法时会出现分段错误,该方法实际上是IODevice基类的方法。

如果我这样做:

    ...
    FilePy* inputFile;
    ...
    inputFile = (FilePy*) cD_py;
    inputFile->isReadable();
    ...

在这种情况下,代码可以正常工作。然而,这是不可取的,因为它假设我们传入一个“FilePy”对象,但事实并非如此;它可能是“SocketPy”或“BufferPy”或“StringPy”或任何其他类型的“IODevice”子类。

似乎Python绑定过程在某种程度上与我们尝试使用的C ++类继承结构不兼容。有没有人试图解决这样的问题?我们的C ++继承是错误的,还是我们应该在Python绑定中做一些不同的事情来使它工作?

1 个答案:

答案 0 :(得分:4)

您的类型FilePy和IODevice是否派生自PyObject?否则,C ++编译器将解释:

inputFile = (IODevice*) cD_py;

为:

inputFile = reinterpret_cast<IODevice*> (cD_py);

而不是您的期望:

inputFile = dynamic_cast<IODevice*> (cD_py);

如果传递的实际类型不是PyObject,或者IODevice通过继承与PyObject无关,那么C ++编译器或运行时就无法知道如何找到合适的vtable。