我有一个已经包装的外部类(我的意思是,它可以通过python直接访问而不需要进一步的努力),现在我希望它是一个更大的cython模块的 part (在换句话说,嵌入它)。
我可以明确地python-import它。但问题是外部类已经在cython模块中的extern
函数中使用(因此该类最终在源代码中#include
)。 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类。
答案 0 :(得分:2)
这应该没问题(差不多)。这条cdef extern
行不太正确:
cdef extern from "some_functions.hpp":
object some_function1(some_type); // this returns a wrapped foo object
注意对object
的更改 - 这告诉Cython该函数返回一个Python对象。 C / C ++声明如下:
PyObject* some_function1(some_type);
// or
Foo_wrapper* some_function1(some_type);
要么工作。
Cython代码可以正常使用的原因是PyObject_HEAD
包含指向ob_type
的指针PyTypeObject FooType
。这是在创建对象时设置的。 PyTypeObject
包含Python解释器使用返回对象所需的所有细节,因此一切都应该正常工作。
整个事情基本上等同于Python代码:
# in "somemodule.py"
def a_function():
import something_else
return something_else.Class()
Python解释器可以使用返回的值,尽管“global”命名空间中不知道Class
。
要注意的一件事是,在创建Foo
之前,应确保至少调用Foo_wrapper
模块初始化函数一次。原因是此函数通常会执行一些操作,例如调用PyType_Ready(&FooType)
以确保FooType
已正确设置。一种简单的方法是将以下行添加到some_function1
:
PyObject* m = PyImport_ImportModule("Foo");
if (m==NULL) return NULL; // an error
Py_CLEAR(m); // don't need to keep a reference to it
但是还有其他方法可以做同样的事情。