【问题标题】:Python ctypes, C++ object destructionPython ctypes,C++ 对象销毁
【发布时间】:2010-09-16 08:34:10
【问题描述】:

考虑以下 python ctypes - c++ 绑定:

// C++
class A
{
public:
    void someFunc();
};

A* A_new() { return new A(); }
void A_someFunc(A* obj) { obj->someFunc(); }
void A_destruct(A* obj) { delete obj; }

# python
from ctypes import cdll

libA = cdll.LoadLibrary(some_path)

class A:
    def __init__(self):
        self.obj = libA.A_new()

    def some_func(self):
        libA.A_someFunc(self.obj)

当不再需要 python 对象时,删除 c++ 对象的最佳方法是什么。

[编辑] 我添加了建议的删除功能,但是问题仍然存在,由谁以及何时调用该函数。应该尽可能方便。

【问题讨论】:

    标签: c++ python ctypes


    【解决方案1】:

    您可以实现__del__ 方法,该方法调用您必须定义的析构函数:

    C++

    class A
    {
    public:
        void someFunc();
    };
    
    A* A_new() { return new A(); }
    void delete_A(A* obj) { delete obj; }
    void A_someFunc(A* obj) { obj->someFunc(); }
    

    Python

    from ctypes import cdll
    
    libA = cdll.LoadLibrary(some_path)
    
    class A:
        def __init__(self):
            fun = libA.A_new
            fun.argtypes = []
            fun.restype = ctypes.c_void_p
            self.obj = fun()
    
        def __del__(self):
            fun = libA.delete_A
            fun.argtypes = [ctypes.c_void_p]
            fun.restype = None
            fun(self.obj)
    
        def some_func(self):
            fun = libA.A_someFunc
            fun.argtypes = [ctypes.c_void_p]
            fun.restype = None
            fun(self.obj)
    

    另请注意,您在 __init__ 方法中遗漏了 self 参数。此外,您必须明确指定返回类型/参数类型,因为 ctypes 默认为 32 位整数,而现代系统上的指针可能是 64 位。

    有些人认为__del__ 是邪恶的。作为替代方案,您可以使用with 语法:

    class A:
        def __init__(self):
            fun = libA.A_new
            fun.argtypes = []
            fun.restype = ctypes.c_void_p
            self.obj = fun()
    
        def __enter__(self):
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            fun = libA.delete_A
            fun.argtypes = [ctypes.c_void_p]
            fun.restype = None
            fun(self.obj)
    
        def some_func(self):
            fun = libA.A_someFunc
            fun.argtypes = [ctypes.c_void_p]
            fun.restype = None
            fun(self.obj)
    
    with A() as a:
        # Do some work
        a.some_func()
    

    【讨论】:

    • 什么时候调用del函数?
    • A的引用计数达到零时,就在对象被清理之前。
    • 当这种情况发生时是否有任何保证?在 python 文档中找不到它们。这是否意味着python决定何时执行__del__
    • @tauran:有关引用计数的信息,请参阅 thisthis
    【解决方案2】:

    一般来说,dll 应该提供一种方法来清理它们创建的对象。这样,内存分配被封装在 dll 中。这意味着,您的 dll 可能应该公开像 void A_delete(A*) 这样的方法。

    【讨论】:

      【解决方案3】:

      从 DLL 中导出一个函数来释放对象。您必须这样做以确保使用相同的内存管理机制来释放在分配对象时负责的对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-02-08
        • 2011-09-18
        • 2010-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多