这应该是一个简单的过程,但它仍然躲避我好几天了。
我的情况如下:
我用 SWIG 包装了一个相对简单的 C++ 接口,所以我可以将它与 Python 一起使用。然而,事情很复杂,因为其中一个方法返回一个自定义结构,其定义如下:
struct DashNetMsg {
uint64_t timestamp;
char type[64];
char message[1024];
};
这是我的 SWIG 接口文件,用于完成此操作:
%module DashboardClient
%{
#include "aos/atom_code/dashboard/DashNetMsg.h"
#include "DashboardClient.h"
%}
%import "aos/atom_code/dashboard/DashNetMsg.h"
%include "DashboardClient.h"
%ignore Recv(DashNetMsg *);
“DashboardClient.h”和“DashboardClient.cpp”声明并定义了“DashboardClient”类及其方法,我正在包装它们。“DashNetMsg.h”是一个头文件,它实际上只包含上述结构定义。下面是 DashboardClient.Recv 方法的定义,来自 DashboadClient.cpp:
DashNetMsg DashboardClient::Recv() {
DashNetMsg ret;
if (Recv(&ret)) {
// Indicate a null message
strcpy(ret.type, "NullMessage");
}
return ret;
}
当我编译它并将其加载到 python 中时,会出现两个有趣且(我认为)相互关联的问题:
Python 3.1.3 (r313:86834, Nov 28 2010, 10:01:07)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import DashboardClient
>>> d = DashboardClient.DashboardClient()
>>> m = d.Recv()
>>> m
<Swig Object of type 'DashNetMsg *' at 0x7f4d4fc2d3c0>
>>> m.type
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'SwigPyObject' object has no attribute 'type'
>>> exit()
swig/python detected a memory leak of type 'DashNetMsg *', no destructor found.
首先,DashNetMsg 显然确实定义了一个名为“type”的属性。其次,这个内存泄漏是怎么回事?根据 SWIG:
如果接口中未定义任何构造函数和析构函数,SWIG 将创建默认构造函数和析构函数。
(http://www.swig.org/Doc2.0/SWIG.html,第 5.5 节)
这是否意味着它应该为这个包装类型创建一个析构函数?另外,为什么我不能访问我的结构的属性?
无效的解决方案
我可以解释正在发生的事情的最佳猜测是 SWIG 出于某种原因实际上并未包装 DashNetMsg 结构,而是将其视为不透明指针。因为 SWIG 似乎表明必须手动释放这些指针指向的内容,所以我猜它也可以解释内存泄漏。但是,即使是这种情况,我也不明白为什么 SWIG 不会包装该结构。
我在这里读到,swig 必须具有声明为 C 风格的结构才能识别它们。因此,我尝试了这个:
typedef struct DashNetMsg {
uint64_t timestamp;
char type[64];
char message[1024];
} DashNetMsg;
它具有与上述完全相同的结果。