1

Pythonで使用したいC++関数があります。

struct DataWrap
{
    wchar_t* data;
    int size;
}

extern int fun1( const char* szInBuffer, unsigned int inSize,DataWrap* buff);

fun1サイズがでchar指定されたsの配列を受け取り、新しく割り当てられたUTF-16文字列を返します。szInBufferinSizedataWrap->data

fun1この関数をPythonから使用したいと思います。

%typemap(argout) DataWrap* buff{
                int byteorder = -1;
                $input = PyUnicode_DecodeUTF16( (const char*)($1->data), ($1->size)*sizeof(wchar_t) , NULL, &byteorder);
}

dataWrap->dataこれは機能しますが、によって割り当てられたfun1が解放されないため、ここでメモリリークが発生します。

私はこれを次のように修正しようとしました:

%typemap(argout) DataWrap* buff{
            int byteorder = -1;
            $input = PyUnicode_DecodeUTF16( (const char*)($1->data), ($1->size)*sizeof(wchar_t) , NULL, &byteorder);
            delete $1;
        }

そして今、コードがクラッシュします。

私は何が間違っているのですか?UTF-16文字列をPythonに取り込むためにSWIGを使用する理由は正しいですか?

4

1 に答える 1

2

タイプマップを試してくださいfreearg

%typemap(freearg) DataWrap *buff {
    delete $1->data;
}

また、あなたは持っていましたdelete $1;。それはすべきdelete $1->dataですか?

編集

この問題で遊んでいるときに、あなたの問題に関連している可能性のある別の問題を発見しました。Windowsを使用していて、の実装がfun1SWIGラッパーコードとは異なるDLLにある場合は、両方のDLLが同じCランタイムDLLにリンクするようにしてください(/MDたとえば、Microsoft VC ++のコンパイラスイッチを介して)。次に、あるDLLに(私が想定しているように)割り当てられnew、別のDLLで解放されます。

これが私が遊んでいたコードです。それはあなたを助けるかもしれません。また、Pythonからの文字列とサイズの送信を排除するためのタイプマップと、一時的なDataWrapオブジェクトを生成するためのタイプマップも含まれているため、渡す必要もありません。実装ファイルx.cppでは、文字列をUTF16に変換する実装を偽造しました。この実装は、単純なASCII文字列でのみ機能します。

freeargまた、タイプマップを使用しても機能しましたが、タイプマップを使用せずに機能するようになったことにも注意してください。

makefile

_x.pyd: x_wrap.cxx x.dll
    cl /MD /nologo /LD /Zi /EHsc /W4 x_wrap.cxx /Id:\dev\python27\include -link /LIBPATH:d:\dev\python27\libs /OUT:_x.pyd x.lib

x.dll: x.cpp x.h
    cl /MD /nologo /Zi /LD /EHsc /W4 x.cpp

x_wrap.cxx: x.h x.i
    swig -python -c++ x.i

xi

%module x

%begin %{
#pragma warning(disable:4127 4211 4706)
%}

%{
    #include "x.h"
%}

%include <windows.i>

%typemap(in) (const char *szInBuffer,unsigned int inSize) {
   if (!PyString_Check($input)) {
       PyErr_SetString(PyExc_ValueError, "Expecting a string");
       return NULL;
   }
   $1 = PyString_AsString($input);
   $2 = PyString_Size($input);
}

%typemap(in, numinputs=0) DataWrap* buff (DataWrap temp) {
   $1 = &temp;
}

%typemap(argout) DataWrap* buff {
    int byteorder = -1;
    $result = PyUnicode_DecodeUTF16((const char*)($1->data), ($1->size)*sizeof(wchar_t), NULL, &byteorder);
    delete [] $1->data;
}

%include "x.h"

xh

#ifdef API_EXPORTS
#   define API __declspec(dllexport)
#else
#   define API __declspec(dllimport)
#endif

struct DataWrap
{
    wchar_t* data;
    int size;
};

extern "C" API void fun1(const char* szInBuffer, unsigned int inSize, DataWrap* buff);

x.cpp

#include <stdlib.h>

#define API_EXPORTS
#include "x.h"

API void fun1(const char* szInBuffer, unsigned int inSize, DataWrap* buff)
{
    unsigned int i;
    buff->size = inSize;
    buff->data = new wchar_t[inSize];
    for(i = 0; i < inSize; i++)
        buff->data[i] = szInBuffer[i];
}

出力

Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import x
>>> x.fun1('abc')
u'abc'
于 2012-04-22T17:08:41.547 に答える