python - 提取 SWIG 包装的 C++ 实例/指针以在 Cython 中使用

标签 python c++ swig cython cpython

我有一个来自 SWIG 包装的 C++ 库的类的实例,我想从中提取它的引用,以便能够在 Cython 文件中使用它,我在其中直接链接到同一个 C++ 库通过使用相同类的更轻量级的自制 Cython 包装器。

我知道这不像访问某些隐藏属性那么容易,但我想如果从 Cython 中链接到 SWIG 或 CPython 中可能有一些函数可能会这样做(也许是一些 PyObject_*?)。

不幸的是,我对 SWIG 或 CPython 内部知识了解不够,不知道如何执行此操作,或者这是否真的可能而不修改 SWIG 绑定(bind)的源代码。

最佳答案

经过进一步研究,我想出了如何做我想做的事。

根据 the documentation ,Python 中 SWIG 包装的类由三层组成:a) 纯 Python 实例,b) 自定义 SwigPyObject built-in type包含在其 .this 属性中,并且 c) 一个通常无法访问的指针 void *ptr 指向其中包含的实际 C++ 实例,这是 Cython 所需要的。

为了访问该指针,我必须创建 SwigPyObject 结构的 Cython 包装器,以便访问 SWIG 实例的内部 void *ptr。此结构的声明通常直接包含在 SWIG 生成的 C++ 源代码中,而不是作为单独的 header ,因此我创建了一个包含它的 header :

#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)

警告:由于 SWIG 包装的类存在于 Python 和 C++ 空间中,SWIG 实现了处理内存分配的机制,包括有关垃圾收集实例“所有权”的信息。此代码不会尝试处理任何这些,因此可能存在遇到分配问题的危险,但只要在 Python 中保留对原始 SWIG 实例的引用,我相信操作它应该是安全的在 Cython 下。

关于python - 提取 SWIG 包装的 C++ 实例/指针以在 Cython 中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28904033/

相关文章:

c++ - 在 C++ 中读入数组

c++ - 断言不起作用

python - %exception 被 SWIG(python) 包装器忽略了吗?

c++ - SWIG: 'module' 对象没有属性 'Decklist'

python - Numpy np.where 多重条件

python - 'function'对象在django中没有属性 'get'

python - 如何为模型中的排序添加字段长度?

python - 从单选按钮获取输入

c++ - 未知像素格式错误 SDL2

python - SWIG——在扩展内部使用类型映射