1

私が書いた科学的な C ライブラリの python ラッパーを作成しています。ライブラリには、コンパイル時にグローバルに定義される double の定数配列が含まれています。

const double arr[NARR] = { 200.0, 201.0, ... 899.0, 900.0 };

SWIG を使用して、これを Python モジュールのモジュール レベルの numpy 配列にします。

>>> import foo
>>> foo.arr
array([200.0, 201.0, ..., 889.9, 900.0])

定数配列でこれを行うためのドキュメントが見つからないようです。すべてが、関数からnumpy配列を返すか、配列以外の定数を定義することを扱っているようです。

配列を手動でラップすることでこれを行う方法を知っています:

npy_intp dim[1] = { NARR };
PyObject *a = PyArray_SimpleNewFromData(1, dim, NPY_DOUBLE, arr);
PyObject_SetAttrString(module, "arr", a);

SWIGで動作させることができません。上記のコードを foo.i ファイルの init ブロックに入れようとすると、「arr」変数が foo モジュールに表示されません。

これを適切に機能させる方法を誰か教えてもらえますか?

編集

seberg からの提案に基づいて、配列を手動でラップするためのコード例を変更しました。

4

1 に答える 1

1

この問題の解決策を見つけましたが、かなりハックです。

ファイルに 2 つのコード拡張を含めましたfoo.i。1 つは C で、もう 1 つは Python です。C 拡張機能は、C 配列を返す関数と、この C 配列を numpy 配列として返すラッパーを作成するよう SWIG に指示するステートメントを作成します。

/* Tell SWIG I want the function to output a numpy array */
%apply double ARGOUT_ARRAY1[ANY] { double a[NARR] };
/* Create a function that returns a copy of the array */
%inline %{
void _get_arr(double a[NARR]) {
    for (int i = 0; i < NARR; i++)
        a[i] = arr[i];
}
%}

Python 拡張機能はこの関数を呼び出し、モジュール レベルの numpy 配列変数に配置しますarr(適切な測定のために読み取り専用にします)。

%pythoncode %{
# Make the arr array a read-only module-level numpy array
arr = _get_arr()
arr.flags.writeable = False
%}

これをパッケージとして配布する__init__.pyので、ファイルにインポートされて ではインポートされ_get_arrない関数を制御できますfoo

望ましい結果が得られました。

>>> import foo
>>> foo.arr
array([200.0, 201.0, ..., 889.9, 900.0])
>>> foo.arr[0] = 10
RuntimeError: array is not writeable
>>> foo._get_arr()
AttributeError: 'module' object has no attribute '_get_arr'
于 2013-01-04T03:20:26.117 に答える