SWIGの新しいビルトイン機能でpythonappendを使う方法はないですか?
質問
私は、SWIGで美しく動作する小さなプロジェクトを持っています。 特に、私の関数のいくつかは
std::vector
を返すのですが、これはPythonのタプルに変換されます。 私は多くの数値を扱うので、c++のコードから返された後、SWIGにこれらをnumpy配列に変換させています。 これを行うために、私はSWIGで次のようなものを使っています。
%feature("pythonappend") My::Cool::Namespace::Data() const %{ if isinstance(val, tuple) : val = numpy.array(val) %}
(実際には、Dataという名前の関数がいくつかあり、そのうちのいくつかは浮動小数点数を返すので、それをチェックするために
val
が実際にはタプルであることを確認するためです)。 これは見事に動作します。
しかし、私はまた、このように
-builtin
フラグが使えるようになりました。 これらの Data 関数の呼び出しはまれで、ほとんどが対話型なので、その遅さは問題ではありませんが、他にも遅いループがあり、組み込みオプションで大幅に高速化されます。
問題は、私がそのフラグを使用するとき、pythonappend 機能が黙って無視されることです。 今、データは単にタプルを再び返します。 まだ numpy 配列を返すことができる何らかの方法はありますか? 私はタイプマップを使用しようとしましたが、それは巨大な混乱に変わりました。
編集してください。
Borealidが非常にうまく質問に答えてくれています。 私はconst参照で戻り、vectorのvectorを使うので必要な、関連するが微妙に異なる2つのtypemapを含む。 これらは十分に異なっているので、他の人が細かい違いを理解しようとしてつまずくことを望まないでしょう。
%typemap(out) std::vector<int>& {
npy_intp result_size = $1->size();
npy_intp dims[1] = { result_size };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(1, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) { dat[i] = (*$1)[i]; }
$result = PyArray_Return(npy_arr);
}
%typemap(out) std::vector<std::vector<int> >& {
npy_intp result_size = $1->size();
npy_intp result_size2 = (result_size>0 ? (*$1)[0].size() : 0);
npy_intp dims[2] = { result_size, result_size2 };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) { for (size_t j = 0; j < result_size2; ++j) { dat[i*result_size2+j] = (*$1)[i][j]; } }
$result = PyArray_Return(npy_arr);
}
2を編集します。
私が求めていたものとは少し違いますが、同様の問題は @MONK さんのアプローチでも解決できるかもしれません ( はここで説明されています。 ).
どのように解決するのですか?
私はあなたの意見に同意します。
typemap
を使うのは少し面倒ですが、このタスクを達成するための正しい方法であることに同意します。また、SWIG のドキュメントには
%pythonappend
とは互換性がありません。
-builtin
とは互換性がありませんが、強く示唆されています。
%pythonappend
は、Python のプロキシクラスに追加される
と組み合わせても、Python プロキシクラスは全く存在しません。
-builtin
フラグと連動して存在しません。
以前、あなたがやっていたことは、SWIG に C++ の
std::vector
オブジェクトを Python のタプルに変換し、そのタプルを再び
numpy
- に戻し、そこで再び変換されます。
本当にしたいことは、Cレベルで一度変換することです。
以下は、すべての
std::vector<int>
オブジェクトをNumPyの整数配列に変換するコードです。
%{
#include "numpy/arrayobject.h"
%}
%init %{
import_array();
%}
%typemap(out) std::vector<int> {
npy_intp result_size = $1.size();
npy_intp dims[1] = { result_size };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(1, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) {
dat[i] = $1[i];
}
$result = PyArray_Return(npy_arr);
}
これは、Cレベルのnumpy関数を使って、配列を構築して返します。順序としては、それは
-
NumPyの
arrayobject.h
ファイルが C++ 出力ファイルに含まれるようにします。 -
原因
import_array
がPythonモジュールがロードされたときに呼び出されるようにします(そうでなければ、すべてのNumPyメソッドはセグメンテーションフォールトを起こします)。 -
のすべての戻り値をマップします。
std::vector<int>
をNumPyの配列にマッピングする。typemap
このコードを配置する
の前に
あなたは
%import
を返す関数を含むヘッダは
std::vector<int>
. この制限の他は、完全に自己完結しているので、コードベースに主観的な混乱を加えることはないでしょう。
もし他のベクトル型が必要なら、単に
NPY_INT
を変更し、すべての
int*
と
int
のビットがあり、それ以外は上記の関数と重複しています。
関連
-
[解決済み] AndroidでPythonを実行する方法はありますか?
-
[解決済み] virtualenvで異なるバージョンのPythonを使用する
-
[解決済み] Pythonで複数行のコメントを作成する方法はありますか?
-
[解決済み] リストの要素を値で削除する簡単な方法はありますか?
-
[解決済み] スレッドを強制終了させる方法はありますか?
-
[解決済み] Pythonのargparseを使った隠し引数の作成
-
[解決済み] DataFrameに日付間の日数カラムを追加する pandas
-
[解決済み] Cythonのコードを含むPythonパッケージはどのように構成すればよいのでしょうか?
-
[解決済み] matplotlib でプロットの軸、目盛、ラベルの色を変更する方法
-
[解決済み] Pythonで、ウェブサイトが404か200かを確認するためにurllibをどのように使用しますか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Pythonのインスタンス変数とクラス変数
-
[解決済み] Pandasの'Freq'タグにはどのような値が有効ですか?
-
[解決済み] CSVデータを処理する際、1行目のデータを無視する方法を教えてください。
-
[解決済み] Celeryタスクのユニットテストはどのように行うのですか?
-
[解決済み] Pandasを使って、既存のExcelファイルに新しいシートを保存する方法は?
-
[解決済み] virtualenv の `--no-site-packages` オプションを元に戻す。
-
[解決済み] Python Empty Generator 関数
-
[解決済み] virtualenvsはどこに作成するのですか?
-
[解決済み] Pythonの辞書にあるスレッドセーフについて
-
[解決済み] 認証プラグイン 'caching_sha2_password' はサポートされていません。