dllは関数だけでなく変数をエクスポートしていることもあります。
Pythonライブラリにある例としてはPy_OptimizeFlag
、
起動時の-Oまたは-OOフラグに依存して、
0, 1または2が設定される整数があります。
ctypes
は型のin_dllクラスメソッドを使ってこのように
値にアクセスできます。pythonapiはPython C apiへのアクセスできるように
するための予め定義されたシンボルです:
>>> opt_flag = c_int.in_dll(pythonapi, "Py_OptimizeFlag") >>> print opt_flag c_long(0) >>>
インタープリタが-Oを指定されて動き始めた場合、サンプルは
c_long(1)
を表示するでしょうし、-OOが指定されたならば
c_long(2)
を表示するでしょう。
ポインタの使い方を説明する拡張例では、Pythonがエクスポートする
PyImport_FrozenModules
ポインタにアクセスします。
Pythonドキュメントからの引用すると: このポインタは メンバーがすべてNULLまたはゼロであるレコードを最後に持つ``struct _frozen``レコードの 配列を指すように初期化されます。 フローズン(frozen)モジュールがインポートされたとき、このテーブルから探索されます。 サードパーティ製コードは動的に作成されたフローズンモジュールの集合を提供するためと、 これにいたずらすることができます。
これで、このポインタを操作することが役に立つことを証明できるでしょう。
例の大きさを制限するために、このテーブルをctypes
を使って読む方法だけを
示します:
>>> from ctypes import * >>> >>> class struct_frozen(Structure): ... _fields_ = [("name", c_char_p), ... ("code", POINTER(c_ubyte)), ... ("size", c_int)] ... >>>
私たちはstruct _frozen
データ型を定義済みなので、このテーブルを指す
ポインタを得ることができます:
>>> FrozenTable = POINTER(struct_frozen) >>> table = FrozenTable.in_dll(pythonapi, "PyImport_FrozenModules") >>>
table
がstruct_frozen
レコードの配列へのpointer
なので、
その配列に対して反復処理を行えます。しかし、ループが確実に終了するように
する必要があります。なぜなら、ポインタに大きさの情報がないからです。
遅かれ早かれ、アクセス違反か何かでクラッシュすることになるでしょう。
NULLエントリに達したときはループを抜ける方が良い:
>>> for item in table: ... print item.name, item.size ... if item.name is None: ... break ... __hello__ 104 __phello__ -104 __phello__.spam 104 None 0 >>>
標準Pythonはフローズンモジュールとフローズンパッケージ(負のサイズのメンバーで
表されています)を持っているという事実はあまり知られておらず、テストにだけ
使われています。例えば、import __hello__
を試してみてください。
ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。