当一个类包含指向另一个类的指针时,SWIG似乎会不恰当地报告另一个类的内容。以下是最小的可重复性示例(SSCCE):
配置h:
class Config
{
int debug;
public:
void showDebug(void);
};
class ConfigContainer
{
Config *config;
public:
ConfigContainer(Config *);
void showDebug(void);
};
在配置.cpp公司名称:
^{pr2}$现在,当我用SWIG翻译成Python时,我得到了:
^{3}$当我在C++中运行这个序列时,报告的内容是相同的。但是对于SWIG,即使地址是相同的,SWIG似乎破坏了地址中的值。在
响应者说,这是因为一旦调用showDebug()
,ConfigContainer的Config *config
成员在Python中的引用计数减少了。在
如何告诉SWIG,告诉Python让config
成员保持独立?在
这看起来是一个终生的问题。在
如果传递给函数的对象将被保存在某个地方,则需要通过递增引用计数器来通知Python运行时。在
如果不这样做,那么对象可能在第一次调用终止后被销毁,因此
config
指针实际上指向Python认为可重用的内存。在您所观察到的是内存实际上已被其他对象重用(因此您可以看到内容的变化)。在
在cpython中,使用引用计数器管理对象生命周期(使用单独的收集算法来解决引用循环的问题)。每个对象都有一个计数器,显示有多少其他对象指向它,每次使用该计数器时都必须保持正确。在
如果你将一个对象传递给一个函数,而函数代码将指向该对象的指针存储在某个地方,那么它也应该增加指向对象的引用计数器。如果它未能通知对象新存储的引用,问题是对象可能会被销毁,留下一个指向未分配(或稍后重用)内存的悬空指针。在
相反的问题(增加引用太多)是内存泄漏,因为如果引用计数器大于零,即使没有人使用它,Python内存管理器也不会回收对象内存。在
请参阅http://docs.python.org/2/c-api/refcounting.html和相关文档。在
当Python创建您的
Config
对象时,它不保存对它的永久引用。您的配置容器类只包含一个简单的指针,所以即使在C++中,如果不保持对象活着,配置容器也不会知道。在下面的代码行使用Python创建一个临时的
Config
对象,该对象在该行完成时被销毁:如果向构造函数和析构函数添加封装外形,可以看到这一点,就像我下面所做的那样:
^{pr2}$所以现在ConfigContainer持有一个被破坏的指针。简单的解决方案是在完成之前保留对
Config
的引用。在复杂的解决方案是实现引用计数(参见6.25 C++ reference counted objects - ref/unref feature)。在
另一个解决方案是通过更改容器来使用SWIG对
std::shared_ptr
的支持:以下文件是必需的接口:
现在,
Config
将被引用计数:ConfigContainer
现在包含对Config
的引用。销毁容器会销毁对Config
的最后一个引用:但是如果Python有它自己的引用,那么当Python处理完它时,只会销毁容器:
相关问题 更多 >
编程相关推荐