6

私は今日、最初の Python 拡張機能を開始しましたが、演習として C ライブラリの非常に小さなラッパーを作成しただけでした。C ライブラリでよくあることですが、ハンドラーを生成する初期化関数から始めます。そのハンドラーを関数に渡し、後でメモリを解放するクリーンアップ関数に渡すことができます。

ラッパーを書き始めたとき、私は基本的に Python から各ネイティブ C 関数を呼び出す方法が必要でした。すぐに、別の関数で C から Python に任意のポインターを返すだけで、そこから C に戻す必要があるという問題にぶつかりました。Python では使用しないので、見た目は関係ありません。保存して渡すだけです。

では、Python と C の間で void ポインターをどのようにやり取りするのでしょうか?

注意: 拡張システムを使用してこのような小さなラッパーを作成することはお勧めできませんが、ctypes やその仲間を使用することをお勧めします。これは今のところ練習用です。

4

2 に答える 2

2

いくつかの検索の後、関数PyLong_AsVoidPtrPyLong_FromVoidPtrを見つけました。void *これにより、 aと a の間で変換する優れた方法が得られますPyObject

# in init function
return PyLong_FromVoidPtr(handle);

# in function using handle
handle = PyLong_AsVoidPtr(python_handle);

1 つの問題は、関数に与えられpython_handleた典型的なものから取得する方法かもしれません。*args

PyObject *python_handle;
PyArg_ParseTuple(args, "O", &python_handle);

"O"ここで注意してください:オブジェクトに与えられる引数は、ポインターへのPyObjectポインターでなければなりません: PyObject **. "O"自体は、処理や変換を行わずにこれを通過させることのみを示しますPyObject。これにより、任意のポインタを好きなように渡すことができます。

: このソリューションはあまりきれいではないと思います。なぜなら、変数を使用する必要があるためです。変数は短時間しか必要としません。

于 2013-11-11T01:05:41.083 に答える
2

PyLong_FromVoidPtr() および PyLong_AsVoidPtr() を悪用して、プログラムに悪意のあるデータを挿入することができます。私は彼らに反対することをお勧めします。

Python には、まさにその仕事のための PyCapsule があります。カプセルは、モジュールまたは Python 空間と C 空間の間で void ptr を安全に交換する方法を提供します。カプセルもタイプセーフです。例が必要な場合は、socket / ssl モジュールと pyexpat / _elementtree モジュールがカプセルを使用して CAPI 構造体を交換します。

http://docs.python.org/3/c-api/capsule.html

于 2013-12-05T21:49:26.063 に答える