2013年1月13日日曜日

Scipy.WeaveでPythonにC++埋め込み 3 変数を返す

変数を返す

数値型を返す

def test_ret_int():
    print "---- Return int ----"
    code = """
    return_val = 1;
    """
    ret = weave.inline(code)
    print "ret:", ret

Cの中でint型作成して返すサンプルです。Cのコードから値を返すときには、決してreturn文を使わないでください。weave内では、codeに書かれたコードに到達する前にreturn_valというSCXXのpy::objectが宣言されています。(生成されたcppファイルを見るとわかります。)return_valに代入された変数はweave.inlineメソッドの戻り値として受け取ることができます。APIを見るとわかりますが、py::objectのCの数値型や文字列型を代入すると、自動的にPythonのオブジェクトに変換してくれます。結果は次のようになります。
---- Return int ----
ret: 1

タプルなどを返す


def test_ret_tuple():
    print "---- Return tuple ----"
    code = """
    if(scxxFlag) {
        // scxx
        py::tuple ret(2);
        py::object tmp(1); ret.set_item(0, tmp);
        tmp = 3.5; ret.set_item(1, tmp);
        return_val = ret;
    } else {
        // Python C API is more reasnable.
        return_val = Py_BuildValue("id", 1, 3.5);
    }
    """
    scxxFlag = 1
    ret = weave.inline(code, ["scxxFlag", ])
    print "ret (scxx):", ret
    scxxFlag = 0
    ret = weave.inline(code, ["scxxFlag", ])
    print "ret (Py/C API):", ret
return_valはpy::object型なので、SCXXのpy::tuple, py::dictなどを代入することも可能ですし、Python/C APIのPyObject*を渡すこともできます。ここでは、if文のscxxFlagが1の場合はSCXXでtupleを、0の場合はPython/C APIでtupleを作成しています。(boolの受け渡しはサポートしていないっぽいので、scxxFlagをbool型にしませんでした。) 出力は以下。
---- Return tuple ----
ret (scxx): (1, 3.5)
ret (Py/C API): (1, 3.5)
両方とも同じ結果になっていますね。 Python/C APIの Py_BuildValue はとても便利なので使った方が良いと思います。フォーマットのiはint、dはdouble, sは文字列(char*), OはPyObject*を意味します。 listもdictも簡単に生成できるので試してみてください。
return_val = Py_BuildValue("[i,d]", 1, 3.5);// List
return_val = Py_BuildValue("{s:i,s:[d,s]}", "abc", 1, "def", 3.5, "Hoge"); // Dict
前回の例とあわせて、これで値の受け渡しができるようになりました。次回は、数値計算を利用している方向けにNumpyのArrayを利用した例を見ていきます。

0 件のコメント:

コメントを投稿