0

私はswigが初めてで、修正できない次の機能があります。

int get_list(IN const char * string, OUT struct entry ** results);

は次のようstruct entryに定義されています。

struct flux_entry
{
    char * addr_str;
    char cc[2];
};

エントリ構造体は適切に Python クラスに変換されます。私はグーグルで検索しましたが、使用できる説明が見つかりませんでした。
次のタプルを返すようにしたい: (元のget_listint 戻り値、結果バッファに基づくエントリ python オブジェクトの python リスト)、しかし argout コード スニペットで C エントリを python オブジェクトに変換する方法がわかりません. 私はこれまでになんとか達成しました:

%typemap(argout) struct entry **
{
    PyObject *o = PyList_New(0);
    int i;
    for(i=0; $1[i] ; i++)
    {
        PyList_Append(o, SWIG_HOW_TO_CONVERT_TO_PYOBJECT($1[i]));
    }
    $result = o;
}

何と交換すればSWIG_HOW_TO_CONVERT_TO_PYOBJECTいいですか?渡さresultsれるのは、(struct entry *) 型へのポインターであると想定され、NULL呼び出す前にに設定され、ポインターget_listの割り当てられた配列に設定する必要がありstruct entry *ます。多分小さなラッパー関数はそれを簡単にすることができますか?

配列は、必要な要素の数を(内部で) 計算した後struct entry、C 関数を使用して C 関数内に割り当てられ、配列の末尾を示すポインターで終了します。mallocget_listNULL

また、どこかで解放されていることを確認したいと思います:)

ありがとう!

4

1 に答える 1

1

これにより、少なくとも機能する出発点が得られるはずです。データがどのように返されたかはまだわかりませんでした。ポインターの配列を返して最後のポインターが NULL になるようにするには、 が必要だと思うので、最後のポインターをセンチネルとしてstruct entry ***設定し、addr_str = NULL入力文字列に部分的に基づいたダミーデータをフィールドに入れます。ニーズに合わせて必要に応じて変更します。

%module example

// Insert the structure definition and function to wrap into the wrapper code.
%{
  struct entry {
    char* addr_str;
    char cc[2];
  };

  int get_list(const char* string, struct entry** results)
  {
    *results = malloc(3 * sizeof(struct entry));
    (*results)[0].addr_str = malloc(10);
    strcpy((*results)[0].addr_str,"hello");
    (*results)[0].cc[0] = string[0];
    (*results)[0].cc[1] = string[1];
    (*results)[1].addr_str = malloc(10);
    strcpy((*results)[1].addr_str,"there");
    (*results)[1].cc[0] = string[2];
    (*results)[1].cc[1] = string[3];
    (*results)[2].addr_str = NULL;
    return 0;
  }
%}

#include <typemaps.i>

// Define the structure for SWIG
struct entry {
  char* addr_str;
  char cc[2];
};

// Define a set of typemaps to be used for an output parameter.

// This typemap suppresses requiring the parameter as an input.
// A temp variable is created and passed instead.
%typemap(in,numinputs=0) struct entry **OUTPUT (struct entry* temp) %{
  $1 = &temp;
%}

// Build a list of tuples containing the two entries from the struct.
// Append the new Python list object to the existing "int" result.
%typemap(argout) struct entry **OUTPUT {
  int i = 0;
  PyObject* out = PyList_New(0);
  while((*$1)[i].addr_str != NULL)
  {
    //PyObject* t = PyTuple_New(2);
    //PyTuple_SET_ITEM(t,0,PyBytes_FromString((*$1)[i].addr_str));
    //PyTuple_SET_ITEM(t,1,PyBytes_FromStringAndSize((*$1)[i].cc,2));
    //PyList_Append(out,t);
    //Py_DECREF(t);
    PyObject* s = SWIG_NewPointerObj(*$1+i,$descriptor(struct entry*),0);
    PyList_Append(out,s);
    Py_DECREF(s);
    ++i;
  }
  $result = SWIG_AppendOutput($result,out);
}

// Since a Python object was created and the data copied for each entry struct,
// free the memory returned in the structure.
//%typemap(freearg) struct entry **OUTPUT {
//  int i=0;
//  while((*$1)[i].addr_str != NULL) {
//    free((*$1)[i].addr_str);
//    ++i;
//  }
//  free(*$1);
//}

// Apply the OUTPUT typemap set to the "results" parameter.
%apply struct entry **OUTPUT {struct entry** results};

// Finally, define the function for SWIG
int get_list(const char* string, struct entry** results);

デモ (Python 3.3):

>>> import example
>>> example.get_list('abcd')
[0, [(b'hello', b'ab'), (b'there', b'cd')]]

それが役立つことを願っています。

編集

タプルの作成をコメントアウトし、entry*代わりにプロキシを保存しました。これは Python オブジェクトをリークしませんが、によって使用するために malloc されたメモリentry*は解放されません。で実験していますが、どこに置くべきかわかりません%extend

于 2013-06-23T23:39:48.257 に答える