6

int ポインターを取り、boost::python を介して公開する関数があります。この関数を Python から呼び出すにはどうすればよいですか?

boost::python を使用した C++ の場合:

void foo(int* i);
...
def("foo", foo);

パイソンで:

import foo_ext
i = 12
foo_ext.foo(i)

結果は

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
foo(int)
did not match C++ signature:
foo(int* i)

では、ポインタを渡す方法は?

4

3 に答える 3

4

簡単な答えは次のとおりです。できません。Python にはポインタがありません

長い答えは次のとおりです。ユースケースに応じてさまざまな回避策があります。

あなたの例では int と int* を使用していることに気付きました。Int (float、str、および bool とともに) は、Python では不変であるため、特殊なケースです。

渡すオブジェクトが実際には int ではないとしましょう。

引数を参照として受け取り、アドレスを取得して実際の関数に渡すラッパー関数を用意します。これは、Python でシームレスに動作します。


わかりました、それは本当に int だったとしましょう。今、あなたは問題を抱えています。渡した int を変更することはできません。同じ解決策を試すと、boost::python は実行時に左辺値について文句を言います。まだいくつかのオプションがあります。

関数が終了した後に int がどのように見えるかを確認する必要がなく、関数が返された後に逆参照へのポインターを追い出さないことがわかっているとします。

ラッパーは、値または const 参照によって int を取得する必要があります。他のすべては同じです。


たぶん、後の状態を確認する必要があるだけです (int は OUT 境界です)。

ラッパー関数は引数を取らず、ローカル int のアドレスを実際の関数に渡します。その値を返します。関数がすでに戻り値を持っている場合は、タプルを返す必要があります。


入力と出力の両方が重要であり、関数が返された後、関数が逆参照へのポインターを追い出さないことがわかっています。

上記の2つを組み合わせます。ラッパーは値によって 1 つの int を取り、別の int を返します。


関数は、関数が返された後、逆参照するポインターを追い払うことを期待しています。

本当に良い解決策はありません。c++ int を含むオブジェクトを c++ で作成して公開できます。ラッパーはそのオブジェクトを参照によって取得し、含まれている int のアドレスを抽出して、実際の関数に渡します。ライブラリが処理を完了するまでオブジェクトを Python で存続させる (そしてガベージ コレクタから安全に保つ) ことは、今や Python ライターの問題です。

于 2010-11-09T20:31:53.883 に答える
1

python.orgのboost.pythonHowToから

おそらく、結果のPythonオブジェクトに引数への生のポインターを含めたいですか?その場合、注意点は、C ++オブジェクトの存続期間がPythonオブジェクトの存続期間より前に終了すると、そのポインターがぶら下がり、Pythonオブジェクトを使用するとクラッシュが発生する可能性があることです。

モジュールの初期化中に可変C++オブジェクトを公開する方法は次のとおりです。

scope().attr("a") = object(ptr(&class_instance));
于 2010-10-07T12:59:57.727 に答える
1

ほとんどの場合、関数への生のポインターの受け渡しを回避できますが、実際に必要な場合は、アダプターを使用して元のオブジェクトへの C++ ポインターの Python オブジェクトを次のように作成できます。

template<typename PtrT>
struct PtrAdapter {
    auto& get(PtrT ptr)  { return *ptr; }
};

次に、ポインター型の Python オブジェクトへのマッピングを定義し、暗黙的な変換を許可します。

class_<Cluster<LinksT>*, noncopyable>(typpedName<LinksT>("ClusterPtr", true, true)
, "Raw hierarchy cluster pointer\n")
    .def("__call__", &PtrAdapter<Cluster<LinksT>*>::get,
        return_internal_reference<>(),
        "referenced cluster")
    ;
register_ptr_to_python<Cluster<LinksT>*>();

元のオブジェクト型にも Python オブジェクト (この場合はCluster<LinksT>) へのマッピングが必要であることに注意してください。

次に、そのような C++ コードの場合:

Cluster<LinksT>* cl = clusters.head();
process(cl);
Id cid = cl->id();

同様の Python コードを使用できます。

cl = clusters.head()
process(cl)
cid = cl.id()
于 2014-01-15T17:34:08.863 に答える