4

私は良いとスタックオーバーフローを検索しましたが、私が探していたものに対する答えを見つけることができませんでした. C++/C# 内から Python 関数の呼び出しをフックする方法はありますか? 関数呼び出しとそのパラメーターをキャプチャしますか?

例で編集:

def a(pOne): //何かをする

def b(): a("a")

したがって、「a」への呼び出しで、C++ でその関数をフックし (関数名がわかっていると仮定)、「a」への呼び出しで C++ 関数/イベントを実行し、C++ 関数/イベントに渡されたパラメーターを値として使用します。 「pOne」に渡されたものの。

ありがとう

4

3 に答える 3

3

やりたいことに応じて、C++ にはいくつかの異なるオプションがあります。

やりたいことを実行する最善の方法は、Python を「拡張」することです。

これを行う私のお気に入りの方法はBoost.Python です

生のC-APIを使用することもできますが、これはお勧めしません。

Boost.Python を使用した埋め込みと拡張の例については、私が取り組んできたこのプロジェクトを参照してください。

于 2013-02-19T22:10:58.363 に答える
0

in-python コードを変更しない理由はありますか? そうでない場合は、拡張モジュールまたは python ctypes呼び出しを dllaに記述し、フックを呼び出すデコレーターでラップしてみませんか?

import my_cpp_module
def hook_a_to_call_my_cpp_module(orig_a):
    def replacement_a(pOne):
        try:
            my_cpp_module.my_cpp_function(pOne)
        finally:
            return orig_a(pOne)
    # 
    return replacement_a

@hook_a_to_call_my_cpp_module
def a(pOne):
    pass

次のように、ソースファイルに触れずにこれを行うこともできますa

# in this other file you import the module that contains function a
import the_py_that_has_a

# next line just to avoid copy-pasting the above code from my answer here again
from the_decorator_from_the_previous_example import hook_a_to_call_my_cpp_module

the_py_that_has_a.a = hook_a_to_call_my_cpp_module(the_py_that_has_a.a)

py コードをまったく変更しない理由がある場合は、コメントに記載していただけますか?

于 2014-06-23T09:43:34.507 に答える
0

C++ コードを書き、それを Python から呼び出せるようにしたい場合は、Python インタープリターの拡張と埋め込みを行います。(実際には、拡張のみです。残りの半分は無視してください。)

基本的に、新しいモジュールを作成すればfoo、誰でもimport foo呼び出すことができ、モジュールが Python ファイルとして実装されているか、動的ライブラリにコンパイルされているfoo.a("a")かは関係ありません。foofoo.pyfoo.cppfoo.so

そのためには、Kyle C が示唆しているように、これを行うための高レベルの方法がいくつかあるため、C API を直接処理する必要はありません。(彼の Boost.Python の提案に加えて、CythonPython に直接公開しながら、C++ と直接やり取りできるほぼ Python 言語でコードを記述できる も参照することをお勧めします。)

しかし、それはあなたが求めたものではありません。あなたができるようにしたいのは、Python コードで定義された関数を取り、それをフックして別のことを行うことです。そのためには、上にリンクされている拡張と埋め込みのドキュメントを読む必要があります。埋め込みインタープリターを作成し、いくつかの動作を再現する必要があります (正確にどれだけフックするかによって異なります) PyObject_Call。そのオブジェクトがa関数であり、そうであれば、フック コードを呼び出します。

これはかなり難しいでしょう。組み込みの Python インタープリターをまだ作成していない場合は、それをフックする方法を考える前に作成してください。

インタープリターの外部からフックするよりも、Python 内からフックする方がおそらくはるかに簡単であることは注目に値します。(「monkeypatching」について聞いたことがない場合は、Google にアクセスしてください。) また、C++ でビルドしたモジュールから Python フック呼び出しコードをいつでも作成したり、.so ファイルを介してコンパイル済みの .so ファイルに直接呼び出したりすることができますctypes


最後に、実行中のインタープリター インスタンスを実行時にフックしたい場合、それはさらに困難です。明らかに、ある種のデバッグ/トレース/などを実行できる必要があります。アタッチとコード挿入、およびその詳細はプラットフォームに完全に依存します。PyObject_Call次に、 ( libpython.so/ Python.dll/ Python.framework/whatever からの) への呼び出しをインターセプトして最初にフックを通過する必要があることを除いて、以前のハード バージョンで行ったのと同じことを行う必要があります。. プラットフォームで SO 呼び出しをフックする方法をまだ知らない場合は、外部から Python コードをフックすることを考える前に、それを学ぶ必要があります。

于 2013-02-19T22:48:22.330 に答える