2011-12-08 14 views
9

私はPython/C APIを初めて使っています...私のPythonに新しい機能を追加しようとしています。組み込みインタプリタは、Cプログラムの一部として記述された拡張Pythonモジュールと対話するスクリプトを実行できます。私のCプログラムはグローバル変数を持っていません。私はこのように物事を維持したいと思います。同時に、PythonにCの機能を公開するために、プログラムの状態にアクセスするためにグローバル変数にアクセスする必要があるときに拡張C関数が必要になります。これをどうやって回避するのですか?Python/C APIでCポインタを渡す

static PyObject* 
CInterface_GetStateInfo(PyObject *self, PyObject *args) 
{ 
    const char *printStr; 
    double stateInfo; 
    State *ptr; 

    if(!PyArg_ParseTuple(args, "s", &printStr)) 
    { 
     return NULL; 
    } 
    printf("Received %s\n", printStr); 

    **//RETRIEVE State *ptr FROM self**  

    stateInfo = ptr->info; 
    return Py_BuildValue("d", currentTime); 
} 

* ptrは周りの状態を渡すためにクリーンな方法は、これは次のようになります。ここでは、ここでは拡張機能がある私はPYINTERFACE_Initializeがメイン

void PYINTERFACE_Initialize(State *ptr, FILE *scriptFile, const char* scriptFileName) 
{ 
    Py_Initialize(); 
    PyObject *module = Py_InitModule("CInterface", CInterfaceMethods); 
    if (PyRun_SimpleFileEx(scriptFile, scriptFileName, 1) != 0) 
    { 
     printf("PYINTERFACE script execution failed!\n"); 
    } 
    **//ADD State *ptr TO module**  
} 

から呼び出された場所に埋め込むことを計画する方法ですか?私は確かにPythonに内部状態を公開する必要はありません。私はカプセルの使用について考えましたが、この種の動作をサポートするカプセルの意図とは思われません。

ありがとうございます!基本的には http://docs.python.org/c-api/capsule.html

PyCObject:あなただけのpython 2.7を使用する場合は、PyCapsuleを使用することができます http://docs.python.org/c-api/cobject.html

: V

答えて

5

あなたには、いくつかの下位互換性をしたいと仮定すると、あなたはPyCObjectsを使用したいですstuffはあなたの不透明なポインタをPythonに変換し、Pythonの中で渡すことができます。そしてPythonでCに戻ったときには、それを展開して使用することができます。

PyCapsulesはいくつかの機能を追加している点を除いて、かなり似ています。主な特徴は、 は、タイプセーフティのレベルを提供するためにCapsuleに名前を格納できるということです。あなたはポインタを追加するには、特定のケースでは、

、あなたはこの(エラーチェックおよび破壊コード削除)を行うことになるでしょう:

PyObject *pystate = PyCObject_FromVoidPtr(State, NULL); 
PyObject *dict = PyModule_GetDict(module); 
PyDict_SetItemString(dict, "CStateObject", pystate); 

# To retrieve it from self (assuming that it is an object) 
PyObject *pystate = PyObject_GetAttrString(self, "CStateObject"); 
State *state = (State *)PyCObject_AsVoidPtr(pystate); 
10

カプセルは基本的にあなたができるのpython-不透明無効ポインタでありますモジュールを回したり、関連付けることができます。彼らはあなたの問題を解決する "道"です。

ここでは、静的である必要のないインスタンスxを使用する例を示します。まず、(あなたはこのような何かをバックそのXのポインタを取得するために、あなたは、Pythonに公開する機能で次に

// wrap the methods to be exposed to python in a module 
// i.e. this is a list of method descriptions for the module 
static PyMethodDef InitializeTurkeyMethods[] = { 

    // this block describes one method.. turkey.do_something() 
    {"do_something", 
    turkey_do_something, // fn pointer to wrap (defined below) 
    METH_VARARGS, 
    "do something .. return an int."}, 

    {NULL, NULL, 0, NULL} // sentinel. 
}; 


int init(X * x) { 

    // initialize embedded python scripting .. 
    // (this method a no-op on second or later calls). 
    Py_Initialize(); 

    // initialize the turkey python module 
    PyObject * module = Py_InitModule("turkey", InitializeTurkeyMethods); 

    // Create a capsule containing the x pointer 
    PyObject * c_api_object = PyCapsule_New((void *)x, "turkey._X_C_API", NULL); 

    // and add it to the module 
    PyModule_AddObject(module, "_X_C_API", c_api_object); 
} 

...このようなあなたのモジュールの何か(エラーチェック取り除か)にこれをポインタを添付実際に)あなたは上記のコードでそれを参照することを開始する前に行くことがあります。ここでは

static PyObject* turkey_do_something(PyObject *self, PyObject *args) {  

    if(!PyArg_ParseTuple(args, ":turkey_do_something")) 
     return NULL; 

    // get the x pointer back from the capsule 
    X * x = (X*)PyCapsule_Import("turkey._X_C_API", 0);  

    // call some fn on x 
    return Py_BuildValue("i", x->some_fn_that_returns_an_int()); 
} 

「turkey._X_C_API」何らかの付加型チェックのためだけの名前である - あなたのアプリケーションのためにここにいくつかの意味のある名前を入れました。トルコはデモモジュールの名前です。

は今、あなたはPythonスクリプトから次のようにこれを呼び出すことができます)(、それと仮定Py_InitModuleを呼び出すときにturkey_do_somethingは、fnを輸出してきたか、に応じて:どのようにするためにhttp://docs.python.org/2/c-api/arg.html

import turkey 

print turkey.do_something() 

はこれをチェックタプルとこれをフォーマットします。http://docs.python.org/3.1/c-api/capsule.htmlカプセルのドコについて

関連する問題