包装和使用返回带有SWIG(python)的结构的函数的问题

时间:2013-09-11 02:55:33

标签: c++ python pointers struct swig

这应该是一个简单的程序,但现在仍然没有让我好几天。

我的情况如下:

我用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”是一个头文件,除了上面的结构定义之外什么都没有。以下是来自DashboadClient.cpp的DashboardClient.Recv方法的定义:

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

这是不是意味着它应该为这个包装类型创建一个析构函数? 另外,为什么我不能访问我的struct的属性?

无效的解决方案

我最好的猜测可以解释发生的事情是SWIG由于某种原因实际上并没有包装DashNetMsg结构,而是将其视为不透明指针。因为SWIG似乎表明释放这些指针指向的必须手动完成,我猜也可以解释内存泄漏。但是,即使是这种情况,我也不明白为什么SWIG不会包装结构。

我读过here swig必须具有声明为C风格的结构才能识别它们。因此,我尝试了这个:

typedef struct DashNetMsg {
  uint64_t timestamp;
    char type[64];
    char message[1024];
} DashNetMsg;

它与上面的结果完全相同。

1 个答案:

答案 0 :(得分:1)

使用SWIG按值返回struct非常棘手。 From their documentation

  

按值返回结构或类数据类型的C函数更难处理...... SWIG只支持指针。

     

SWIG分配一个新对象并返回对它的引用。用户在不再使用时删除返回的对象。显然,如果您不知道隐式内存分配并且不采取措施来释放结果,这将泄漏内存。