Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在cython模块中使用外部包装类?_Python_C++_Cython - Fatal编程技术网

Python 如何在cython模块中使用外部包装类?

Python 如何在cython模块中使用外部包装类?,python,c++,cython,Python,C++,Cython,我有一个已经包装好的外部类(我的意思是,python无需进一步努力即可直接访问它),现在我希望它成为更大的cython模块的一部分(换句话说,嵌入它) 我可以直接导入它。但问题是,外部类已经在cython模块中的extern函数中使用(因此该类最终在源代码中被#included)。Python导入需要编译模块,那么这两个模块可能有同一类的两个不同副本 然后我应该如何使用cython中已经包装好的外部类 (可能过于简化)示例: Foo.cpp: #include "Python.h" #incl

我有一个已经包装好的外部类(我的意思是,python无需进一步努力即可直接访问它),现在我希望它成为更大的cython模块的一部分(换句话说,嵌入它)

我可以直接导入它。但问题是,外部类已经在cython模块中的
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方面添加了它。谢谢