Python 如何在cython模块中使用外部包装类?
我有一个已经包装好的外部类(我的意思是,python无需进一步努力即可直接访问它),现在我希望它成为更大的cython模块的一部分(换句话说,嵌入它) 我可以直接导入它。但问题是,外部类已经在cython模块中的Python 如何在cython模块中使用外部包装类?,python,c++,cython,Python,C++,Cython,我有一个已经包装好的外部类(我的意思是,python无需进一步努力即可直接访问它),现在我希望它成为更大的cython模块的一部分(换句话说,嵌入它) 我可以直接导入它。但问题是,外部类已经在cython模块中的extern函数中使用(因此该类最终在源代码中被#included)。Python导入需要编译模块,那么这两个模块可能有同一类的两个不同副本 然后我应该如何使用cython中已经包装好的外部类 (可能过于简化)示例: Foo.cpp: #include "Python.h" #incl
extern
函数中使用(因此该类最终在源代码中被#include
d)。Python导入需要编译模块,那么这两个模块可能有同一类的两个不同副本
然后我应该如何使用cython中已经包装好的外部类
(可能过于简化)示例: Foo.cpp:
#include "Python.h"
#include "foo.hpp"
struct Foo_wrapper {
PyObject_HEAD
foo bar;
};
static int Foo_init(Foo_wrapper* self, PyObject* args, PyObject*) {
....
}
static PyTypeObject FooType {...};
Spam.pyx:
cdef extern from "some_functions.hpp":
cdef some_function1(some_type); // this returns a wrapped foo object
def spam(arg1, arg2, arg3):
// wrap arg1, arg2, arg3 to some_type
return some_function1(an_instance_of_some_type); // huh? but foo isn't available here!
我想在spam.pyx
中使用foo类,这应该很好(几乎)就是这样。这条cdef-extern
行不太正确:
cdef extern from "some_functions.hpp":
object some_function1(some_type); // this returns a wrapped foo object
注意对对象的更改
——这告诉Cython函数返回一个Python对象。C/C++声明如下所示:
PyObject* some_function1(some_type);
// or
Foo_wrapper* some_function1(some_type);
两者都可以
Cython代码可以使用它的原因是PyObject\u HEAD
包含一个指向PyTypeObject FooType
的指针ob\u type
。这是在创建对象时设置的。PyTypeObject
包含Python解释器使用返回对象所需的所有细节,因此一切都应该正常工作
整个过程基本上相当于Python代码:
# in "somemodule.py"
def a_function():
import something_else
return something_else.Class()
Python解释器可以使用返回的值,尽管在“全局”命名空间中不知道类
需要注意的一点是,在创建
Foo\u包装器之前,应确保至少调用了Foo
模块初始化函数一次。原因是此函数通常执行一些操作,如调用PyType\u Ready(&FooType)
以确保正确设置FooType
。一种简单的方法是将以下行添加到某些函数1
:
PyObject* m = PyImport_ImportModule("Foo");
if (m==NULL) return NULL; // an error
Py_CLEAR(m); // don't need to keep a reference to it
不过,还有其他方法可以做同样的事情。我认为Python导入是正确的。我不认为有什么问题,除非这两个定义最终不同(即编译模块1、更改类、编译模块2)。这个问题只需要一个最小的完整示例即可。@DavidW,我认为直接导入是不对的。但如果你这么说的话,我会试一试。我不认为因为你定义了两个空类Foo和Bar,那么Foo和Bar是同一个逻辑类,但对解释器来说不是。或者,如果您在两个不同的模块中使用相同的名称定义两个类,它们仍然不相同。这就是为什么一些代码的简单示例会有所帮助的原因。我不是100%清楚你到底在做什么@大卫,请看增加的例子。这澄清了很多事情。让我想一想。根据我对你答案的理解,(如果我错了,请纠正我),我只需要注册类型以便译员识别。注册是通过PyType\u Ready
完成的,一旦调用了函数,解释器就会知道类型。此外,如果该函数是本机完成的,则应该在cython模块init函数中调用该函数。是吗?基本上是这样。如果Foo.cpp
已经编译成Python模块,那么我认为在某处(可能在some\u function1
或从Cython)导入模块比自己调用PyType\u Ready
更干净。如果Foo.cpp
从未被编译到Python模块,那么从Cython模块init函数调用PyType_Ready
(即在.pyx文件的全局范围内调用它)与任何东西都一样好。是否可以理想地用init将其包装为实际类?或者我将不得不使用一些工厂功能。(是的,在本例中,some_function 1在某种程度上是一个工厂函数。)您添加到TypeObject
Yap中,我拥有该函数,但无法从模块访问它。我只调用了PyType_Ready,没有将它添加到模块名称空间中。不过,我还是设法从python方面添加了它。谢谢