说我有这个结构:
g
我们只说g
是:
Class
我不想将Foo类重新制成python模块,因为它表示库中具有更多函数和变量的类(但这与该问题无关)。我从文档中并没有真正理解如何在C / C ++中创建带有参数的PyObject *,更不用说如何使用C / C ++指针作为参数了。
我要退出本指南:https://docs.python.org/3/extending/newtypes_tutorial.html
我确实有本指南中的dealloc,new和init方法,但除对象本身的实例外,我没有尝试初始化和释放任何值。
这个问题类似于Build a PyObject* from a C function?,但我想传递对象指针而不是函数。我正在使用与Create an object using Python's C API相同的方法来创建对象,但是我不知道如何将foo的实例提供给PyObject。
答案 0 :(得分:2)
我认为您正在使事情变得比试图用指针调用构造函数更为复杂。您的tp_new
和tp_init
方法旨在为创建对象实例提供Python接口。如果提供Python接口没有意义(例如,如果必须始终使用C ++指针创建对象),则只需不提供它们-将它们设置为NULL
,则不会可通过Python创建。
在C ++中,您不受此接口的限制。您可以根据自己的喜好定义自己的“ C ++工厂函数”:
PyFoo* make_PyFoo(Foo* myfoo) {
首先分配对象:
PyFoo *obj = (PyFoo*)(type->tp_alloc(type, 0));
# or
PyFoo *obj = PyObject_New(PyFoo, type); # use PyObject_GC_new if it has cyclic references
如果您尚未定义自定义分配器,则这两种方法几乎等效。这里省略了一些错误检查。...
接下来,您可以简单地使用现有的Foo*
指针来初始化相关字段:
obj->myfoo = myfoo;
然后仅return obj
(并合上括号)。
这个答案在很大程度上是由于我长期以来对Python胶囊的厌恶。很难看到适合他们的用例,但是人们还是喜欢使用它们。
答案 1 :(得分:0)
因此您可以使用胶囊来做到这一点。
创建对象时:
Foo* myFoo = new Foo();
PyObject* capsule = PyCapsule_New((void*) myFoo, "Foo", NULL);
PyObject* argList = Py_BuildValue("(O)", capsule);
PyObject *obj = PyObject_CallObject((PyObject*) &Foo_PyTypeObject, argList);
Py_DECREF(arglist);
Py_DECREF(capsule); // I don't need python to keep the reference to myFoo
Foo_PyTypeObject应该是您为扩展对象创建的PyTypeObject。
然后我在“新”功能中使用了胶囊。
Foo_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
{
Foo* self;
self = (Foo*) type->tp_alloc(type, 0);
if (self != NULL)
{
static char *kwlist[] = {const_cast<char*>("Foo"), NULL};
PyObject* capsule = NULL;
PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &capsule);
self->myFoo = (Foo*) PyCapsule_GetPointer(capsule, "Foo"); // this is the myFoo in the PyFoo struct
Py_DECREF(capsule);
}
return (PyObject*) self;
}