我正在尝试使用SWIG封装一个预先存在的库接口,该接口期望调用方管理某些const char *
值的生存期。
struct Settings {
const char * log_file;
int log_level;
};
// The Settings struct and all members only need to be valid for the duration of this call.
int Initialize(const struct Settings* settings);
int DoStuff();
int Deinitialize();
我开始使用对SWIG的最基本输入来包装库:
%module lib
%{
#include "lib.h"
%}
%include "lib.h"
这将导致有关可能的内存泄漏的SWIG警告:
lib.h(2) : Warning 451: Setting a const char * variable may leak memory.
[通过观察lib_wrap.c
完全可以理解,SWIG生成的代码会将malloc
缓冲区放入log_file
值,但从不释放它:]
SWIGINTERN PyObject *_wrap_Settings_log_file_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct Settings *arg1 = (struct Settings *) 0 ; char *arg2 = (char *) 0 ; void *argp1 = 0 ; int res1 = 0 ; int res2 ; char *buf2 = 0 ; int alloc2 = 0 ; PyObject *swig_obj[2] ; if (!SWIG_Python_UnpackTuple(args, "Settings_log_file_set", 2, 2, swig_obj)) SWIG_fail; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Settings, 0 | 0 ); if (!SWIG_IsOK(res1)) { SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Settings_log_file_set" "', argument " "1"" of type '" "struct Settings *""'"); } arg1 = (struct Settings *)(argp1); res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); if (!SWIG_IsOK(res2)) { SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Settings_log_file_set" "', argument " "2"" of type '" "char const *""'"); } arg2 = (char *)(buf2); if (arg2) { size_t size = strlen((const char *)((const char *)(arg2))) + 1; arg1->log_file = (char const *)(char *)memcpy(malloc((size)*sizeof(char)), arg2, sizeof(char)*(size)); } else { arg1->log_file = 0; } resultobj = SWIG_Py_Void(); if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); return resultobj; fail: if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); return NULL; }
如果将
log_file
的类型更改为char *
,则警告消失,并且似乎多次尝试设置log_file
的值将不再泄漏内存:
SWIGINTERN PyObject *_wrap_Settings_log_file_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { PyObject *resultobj = 0; struct Settings *arg1 = (struct Settings *) 0 ; char *arg2 = (char *) 0 ; void *argp1 = 0 ; int res1 = 0 ; int res2 ; char *buf2 = 0 ; int alloc2 = 0 ; PyObject *swig_obj[2] ; if (!SWIG_Python_UnpackTuple(args, "Settings_log_file_set", 2, 2, swig_obj)) SWIG_fail; res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Settings, 0 | 0 ); if (!SWIG_IsOK(res1)) { SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Settings_log_file_set" "', argument " "1"" of type '" "struct Settings *""'"); } arg1 = (struct Settings *)(argp1); res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); if (!SWIG_IsOK(res2)) { SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "Settings_log_file_set" "', argument " "2"" of type '" "char *""'"); } arg2 = (char *)(buf2); if (arg1->log_file) free((char*)arg1->log_file); if (arg2) { size_t size = strlen((const char *)(arg2)) + 1; arg1->log_file = (char *)(char *)memcpy(malloc((size)*sizeof(char)), (const char *)(arg2), sizeof(char)*(size)); } else { arg1->log_file = 0; } resultobj = SWIG_Py_Void(); if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); return resultobj; fail: if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); return NULL; }
但是,当
log_file
对象在Python中被垃圾回收时,仍然似乎泄漏了为Settings
分配的内存。
以避免这些内存泄漏的方式在SWIG中管理char *
结构值的生存期的推荐方法是什么?
我正在尝试使用SWIG封装一个预先存在的库接口,该接口期望调用方管理某些const char *值的生存期。结构设置{const char * log_file; int ...
您可以告诉SWIG对char*
使用log_file
语义。不幸的是,似乎无法使用Settings::log_file
(所需的memberin
不会显示在模式匹配中),因此,如果该数据成员名称也与其他类型一起使用,则可能会发生冲突但语义不同。看起来像: