2010-11-28 7 views
2

お返事ありがとうございます:) 私はあなたが何を示唆しているか理解していると思いますが、それは私が必要とするものではありません。正直言って、私は必要なことをするための正しい技法が何か分かりません。PythonをC++で埋め込む - C++プログラムからPythonを実行する

私は実行中に時々いくつかのタスクを実行するためにpythonを呼び出す必要があるプログラムを持っています。 Pythonを呼び出してpythonsをキャッチする関数が必要です。

  pythonCallBackFunc(const char* pythonInput) 

この関数はこれを行う関数です。例えば

 pythonCallBackFunc("5**2") needs to print on stdin(or some other file): 
    PythonResult: 25 
    pythonCallBackFunc("print 5**2") needs to print on stdin(or some other file): 
    PythonResult: 25 
    pythonCallBackFunc("'a'+'b'") needs to print on stdin(or some other file): 
    PythonResult: 'ab' 
    pythonCallBackFunc("print 'a'+'b'") needs to print on stdin(or some other file): 
    PythonResult: ab 
    pythonCallBackFunc("execfile('temp.py')") 
    it should print nothing but is needs to run the temp.py script 

    the next 2 calls need to print the value of result, meaning 4. 
    pythonCallBackFunc("result = 4") 
    pythonCallBackFunc("print result") 

私の問題は、与えられたコマンド(pythonInput)についてすべてのpython出力をキャッチすることです。私が試した最初のものは、このスクリプトを使用してファイルにPythonのsdtoutとstderrをリダイレクトすることです:

#stdout.py 
    import sys 
    saveout = sys.stdout          
    fsock = open('out.log', 'w')       
    sys.stdout = fsock          

    #stdout_close.py 
    sys.stdout = saveout          
    fsock.close()   

    #stdout_close.py 
    fsock = open('error.log', 'w')   
    sys.stderr = fsock 

とリダイレクトした後、私はそれはOKだったが、この機能は無視

をPy_run_SimpleString機能を使用しましたこのコマンドの種類:

Py_run_SimpleString("'a'+'b'") 

出力は空だった....

アレックス

+0

私はそれを取得しません。あなたはeval - boostOutputStrに格納されている "5 * 5 + 9"を返します。値は34で、あなたはcout << "Python:" << boostOutputStrを実行します。 – pyfunc

+0

Pythonを組み込むことは、選択肢があるときには、通常は最適ではない設計であることに注意してください。 http://twistedmatrix.com/users/glyph/rant/extendit.html –

答えて

0

まず、些細なインタプリタよりも複雑なものを構築しようとしている場合は、スバナーの答えを読んで理解してください。しかし、この特定のケースでは、あなたは

std::string boostOutputStr = extract<std::string>(str(result)); 

でライン

int boostOutputStr = extract<int>(result); 

を交換し、あなたが探しているものを手に入れることができます。 str(result)部分は、Python式が評価されたどのような型であれ、文字列表現に変換します。必要なのは、std :: coutに書くだけで十分です。あなたがテンプレートpythonCallBackFunc()で行くことに決めた場合

2つのことに注意します

(1)の宣言は、戻り値の型ではなく

(2)あなたがすべき「無効」よりも「がReturnType」を持っている必要があります(初期化された静的なbool(初期化された){Py_Initialize();初期化された= true;} ')

+0

応答に感謝、私は質問を更新しました。私はこのようなものを探していたが、すべてを解決するわけではない。たとえば、次のコマンドを入力しても機能しません。 pythonCallBackFunc( "print 'a' + 'b'") ab – alexpov

5

使用しているサンプルコードは、PythonコードがC++タイプintで表すことができるオブジェクトを返すときにのみ機能します。この動作は、コードのこの行によって引き起こされる:

int boostOutputStr = extract<int>(result); 

あなたが対処しなければならない一般的な問題は、Pythonではないのに対し、C++は、厳密に型指定された言語であるということです。 Pythonの文(またはPythonの関数呼び出し)は任意の型のオブジェクトを返すことができ、関数への1つの呼び出しは、同じ関数への次の呼び出しとは異なる種類のオブジェクトを返すことができます。 C++では、関数の戻り値の型(および引数の型)も明確に定義されていなければなりません。しかし、C++では、より柔軟にするためのテンプレートが用意されています。 1つのテンプレート関数を定義することで(boost :: pythonの抽出関数が良い例です)、この関数をさまざまな型の設定に使うことができます。ただし、テンプレートファンクションコードは、使用するすべてのタイプごとにコンパイラによってインスタンス化されます。私。テンプレートメソッドでは、コピー&ペーストの面倒な作業を省き、使用するすべてのタイプのコードを変更できます。コンパイラはあなたにそれを知っています。コンパイル時にはすべての型を明確に定義する必要があります。関数の復帰をユーザ入力によってはint、時にはstringにすることはできません。 Pythonや他の高水準言語のようなスクリプト言語はこれが役に立ちます。 C++では、コードのコンパイル時にすべての型を設定する必要があります。

あなたの状況でどうしたらいいですか?

pythonCallBackFuncresultに直接、intに変換せずに返すことができます。したがって戻り値はタイプobject(boost :: pythonから)で、Pythonオブジェクトを表します。 extract<>でそれを後であなたのコードに必要なものに変換することができます。 (私はあなたのPython式の戻り値が実際にコードに戻され、いつもcoutを通して出力されないことを前提としています。)

また、関数pythonCallBackFuncもテンプレート化された関数にすることができます。あなたは、これはあなたのための助けにある希望

 pythonCallBackFunc<int>(inputStr); 

例えばとして、適切な型とそれを呼び出す必要があるだろう。その場合には

template<class ReturnType> 
    void pythonCallBackFunc(string inputStr){ 
     Py_Initialize(); 
     try 
     { 
     str boostInputStr(inputStr.c_str()); 
     object result = eval(boostInputStr); 

     return extract<ReturnType>(result); 

     //Py_Finalize() #not calling because of the boost.python 
      } 
      catch(error_already_set const &) 
      { 
     //do somthing 
      } 
    } 

...。

+0

応答に感謝します、それは私が必要とするものではありません。私はdeterrently質問を策定しようとしました... – alexpov

0
のような静的変数で保護してください。

あなたは単に文字列を解析し、PyRun_SimpleStringを使うことができます。

関連する問題