我有一个来自 SWIG 包装的 C++ 库的类的实例,我想从中提取其引用,以便能够在 Cython 文件中使用它,在该文件中,我通过使用直接链接到同一个 C++ 库更轻量级的自制 Cython 同类包装器。
我知道这不会像访问某些隐藏属性那么容易,但我想 SWIG 或 CPython 中可能有一些函数,如果从 Cython 中链接到它(可能是某些 PyObject_* ?)
不幸的是,我对 SWIG 或 CPython 内部的了解不够,不知道如何做到这一点,或者在不修改 SWIG 绑定(bind)的源代码的情况下这是否真的可行。
最佳答案
经过进一步的研究,我想出了如何做我想做的事。
根据 the documentation ,Python 中的 SWIG 包装类由三层组成:a) 纯 Python 实例,b) 包含在其 .this
属性中的自定义 SwigPyObject built-in type 和 c) 通常无法访问的指针 void *ptr
指向其中包含的实际 C++ 实例,其中是 Cython 需要的。
为了访问该指针,我必须创建 SwigPyObject 结构的 Cython 包装器,以便访问 SWIG 实例的内部 void *ptr
。这个结构的声明通常直接包含在 SWIG 生成的 C++ 源代码中,而不是作为单独的头文件,所以我创建了一个来包含它:
#include <Python.h>
typedef struct {
PyObject_HEAD
void *ptr; // This is the pointer to the actual C++ instance
void *ty; // swig_type_info originally, but shouldn't matter
int own;
PyObject *next;
} SwigPyObject;
然后在 Cython
.pxd
文件中引用此包含文件,以启用对内部 ptr
变量的访问:cdef extern from "swigpyobject.h":
ctypedef struct SwigPyObject:
void *ptr
现在可以从
.pyx
Cython 源代码中引用所需的指针: cdef SwigPyObject *swig_obj = <SwigPyObject*>pythonswig.this
cdef MyCppClass *mycpp_ptr = <MyCppClass*?>swig_obj.ptr
// And if you want a proper instance instead of a pointer:
cdef MyCppClass my_instance = deref(mycpp_ptr)
警告:由于 Python 和 C++ 空间中都存在 SWIG 包装的类,因此 SWIG 实现了处理内存分配的机制,包括有关垃圾收集实例的“所有权”的信息。这段代码不会尝试处理任何这些,因此可能存在遇到分配问题的危险,但是只要在 Python 中保留对原始 SWIG 实例的引用,我相信操作它应该是安全的在 Cython 下。
关于python - 提取 SWIG 包装的 C++ 实例/指针以在 Cython 中使用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28904033/