我有两个不同的 Python 扩展模块;我们称它们为 A 和 B。模块 A 包含一个称为容器的存储类类型,我想在模块 B 中将其用作类方法的返回类型。
我似乎找不到任何关于我应该如何执行此操作的文档。我大致按照这篇文章来创建模块/类,除了我没有将所有方法声明为静态的,所以它们可以访问:http://nedbatchelder.com/text/whirlext.html
那么我的问题是,如何创建一个容器实例,我可以将其作为模块 B 中类方法的 PyObject* 返回值传回?容器定义如下所示:
typedef struct {
PyObject_HEAD
storageclass* cnt_;
} container;
我尝试在相关方法中简单地执行以下操作,其中 container_init 是我为容器类注册为 tp_init 的方法:
pycnt::container* retval;
pycnt::container_init(retval, NULL, NULL);
return (PyObject*)retval;
然而,根据 Python 解释器,我正在取回调用该方法的类。 (即,myclassinstance.mymethod() 正在返回 myclassinstance)。
显然我的做法是错误的,但我不知道正确的方法是什么。有什么建议么?只是为了打断任何人的建议——不,我对使用 SWIG 或 Boost::Python 不感兴趣。我已经尝试过了,但容器的底层存储类都不能很好地发挥作用(SWIG 甚至无法解析它)。到目前为止,我自己进行扩展非常轻松,但我在这个问题上遇到了困难。
最佳答案
你的问题是 type->tp_init
没有做你想做的事。 type->tp_init
在分配对象以进行实例化后调用。您首先必须使用 type->tp_new
分配对象,然后将该对象作为第一个参数传递给 type->tp_init
。由于您将未初始化的指针传递给 tp_init
,因此所有赌注都已取消。不过,您通常不会直接调用任何一个函数,而是对类型对象本身调用 PyObject_Call*()
之一来创建新实例。或者提供一个普通的 C 函数来创建一个新实例,如 PyFoo_New()
。
也就是说,在两个扩展模块之间进行相互通信的通常方法是通过 Python API 进行。如果你想让模块 B 导入和使用模块 A,你调用 PyImport_Import()
获取模块对象,调用 PyObject_GetAttrString()
获取你关心的类型对象,以及PyObject_Call*()
之一来实例化它。任何你想存储指向该类型的指针的地方,你只需要一个 PyObject *
。
关于python - 在 Python C API 中使用多个模块/类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2136337/