python ctypes 垃圾回收

标签 python ctypes

我正在使用 ctypes 从 python 访问 c 库(它实际上是 c++ 代码):

class CRMeAnnotationList(object):
def __init__(self):
    self.obj = lib.CRMeAnnotationList_new()de
def __del__(self):
    if self.obj:
        lib.CRMeAnnotationList_destroy(self.obj)
lst = CRMeAnnotationList()

C 代码如下所示

extern "C" {__declspec(dllexport) CRMeAnnotationList* CRMeAnnotationList_new() 
                { return new CRMeAnnotationList(); 
                }
            __declspec(dllexport)void CRMeAnnotationList_destroy(CRMeAnnotationList* p)
                {
                if (p)
                    delete p;
                }
            }

这段代码给了我 完成,退出代码 -1073741819 (0xC0000005)

而如果我不销毁指针,我会得到 0 作为退出代码。

这是否意味着我不需要销毁该指针,即执行 python 代码中的析构函数部分 del

最佳答案

您可能正在运行 64 位 Python,并且尚未正确设置 .argtypes.restype

示例:

测试.cpp

#define API __declspec(dllexport) // Windows-specific

extern "C" {

struct CRMeAnnotationList {
    int a;
};

API CRMeAnnotationList* CRMeAnnotationList_new() {
    return new CRMeAnnotationList();
}

API void CRMeAnnotationList_destroy(CRMeAnnotationList* p) {
    if(p)
        delete p;
}

}

测试.py

from ctypes import *

lib = CDLL('test')
lib.CRMeAnnotationList_new.argtypes = None
lib.CRMeAnnotationList_new.restype = c_void_p
lib.CRMeAnnotationList_destroy.argtypes = c_void_p,
lib.CRMeAnnotationList_destroy.restype = None

class CRMeAnnotationList:

    def __init__(self):
        print(f'created   {id(self):#x}')
        self.obj = lib.CRMeAnnotationList_new()

    def __del__(self):
        print(f'destroyed {id(self):#x}')
        if self.obj:
            lib.CRMeAnnotationList_destroy(self.obj)

lst = CRMeAnnotationList()

输出:

created   0x2232dfc35c0
destroyed 0x2232dfc35c0

.argtypes.restype 行被注释掉时的输出:

created   0x1c98e8f35c0
destroyed 0x1c98e8f35c0
Exception ignored in: <function CRMeAnnotationList.__del__ at 0x000001C98E9176A8>
Traceback (most recent call last):
  File "C:\Users\metolone\Desktop\test.py", line 16, in __del__
OSError: exception: access violation reading 0xFFFFFFFF8C6CABCF

记下访问冲突的地址。它是一个 32 位值,符号扩展为 64 位。

关于python ctypes 垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54066070/

相关文章:

python - Flask + uwsgi + 线程

python - 无法从 Python 连接到在 Azure Linux VM 上运行的 Redis 实例

python - ctypes - 查看返回结构的 c_char_p 字段

python - 带有回调 : access violation on exit 的 ctypes

python : multiprocessing and Array of c_char_p

python - Python中如何进行C语言计算

python - 在 Python 中获取 ctypes 结构的二进制表示

python - 执行 pandas 数据透视表操作时没有要聚合的数字类型

python - AWS - Lambda 无法通过 Python SDK 调用另一个 lambda

python - 如何根据Python列表中出现在该元素之前的元素来访问该元素