16.16. "ctypes" --- Pythonのための外部関数ライブラリ
****************************************************

======================================================================

"ctypes" は Python のための外部関数ライブラリです。このライブラリは C
と互換性のあるデータ型を提供し、動的リンク/共有ライブラリ内の関数呼び
出しを可能にします。動的リンク/共有ライブラリを純粋な Python でラップ
するために使うことができます。


16.16.1. ctypesチュートリアル
=============================

注意: このチュートリアルのコードサンプルは動作確認のために "doctest"
を使います。コードサンプルの中には Linux、 Windows、あるいは Mac OS X
上で異なる動作をするものがあるため、サンプルのコメントに doctest 命令
を入れてあります。

注意: いくつかのコードサンプルで ctypes の "c_int" 型を参照しています
。 "sizeof(long) == sizeof(int)" であるようなプラットフォームでは、こ
の型は "c_long" のエイリアスです。そのため、 "c_int" 型を想定している
ときに "c_long" が表示されたとしても、混乱しないようにしてください ---
実際には同じ型なのです。


16.16.1.1. 動的リンクライブラリをロードする
-------------------------------------------

動的リンクライブラリをロードするために、 "ctypes" は *cdll* をエクスポ
ートします。 Windows では *windll* と *oledll* オブジェクトをエクスポ
ートします。

これらのオブジェクトの属性としてライブラリにアクセスすることでライブラ
リをロードします。 *cdll* は、標準 "cdecl" 呼び出し規約を用いて関数を
エクスポートしているライブラリをロードします。それに対して、 *windll*
ライブラリは "stdcall" 呼び出し規約を用いる関数を呼び出します。
*oledll* も "stdcall" 呼び出し規約を使いますが、関数が Windows
"HRESULT" エラーコードを返すことを想定しています。このエラーコードは関
数呼び出しが失敗したとき、 "OSError" 例外を自動的に送出させるために使
われます。

バージョン 3.3 で変更: Windows エラーは以前は "WindowsError" を送出し
ていましたが、これは現在では "OSError" の別名になっています。

Windows用の例ですが、 "msvcrt" はほとんどの標準 C 関数が含まれている
MS 標準 C ライブラリであり、 cdecl 呼び出し規約を使うことに注意してく
ださい:

   >>> from ctypes import *
   >>> print(windll.kernel32)  
   <WinDLL 'kernel32', handle ... at ...>
   >>> print(cdll.msvcrt)      
   <CDLL 'msvcrt', handle ... at ...>
   >>> libc = cdll.msvcrt      
   >>>

Windows では通常の ".dll" ファイル拡張子を自動的に追加します。

注釈:

  "cdll.msvcrt" 経由で標準 C ライブラリにアクセスすると、Python が使用
  しているライブラリとは互換性のない可能性のある、古いバージョンのライ
  ブラリが使用されます。可能な場合には、ネイティブ Python の機能を使用
  するか、"msvcrt" モジュールをインポートして使用してください。

Linux ではライブラリをロードするために拡張子を *含む* ファイル名を指定
する必要があるので、ロードしたライブラリに対する属性アクセスはできませ
ん。 dll ローダーの "LoadLibrary()" メソッドを使うか、コンストラクタを
呼び出して CDLL のインスタンスを作ることでライブラリをロードするかのど
ちらかを行わなければなりません:

   >>> cdll.LoadLibrary("libc.so.6")  
   <CDLL 'libc.so.6', handle ... at ...>
   >>> libc = CDLL("libc.so.6")       
   >>> libc                           
   <CDLL 'libc.so.6', handle ... at ...>
   >>>


16.16.1.2. ロードしたdllから関数にアクセスする
----------------------------------------------

dll オブジェクトの属性として関数にアクセスします:

   >>> from ctypes import *
   >>> libc.printf
   <_FuncPtr object at 0x...>
   >>> print(windll.kernel32.GetModuleHandleA)  
   <_FuncPtr object at 0x...>
   >>> print(windll.kernel32.MyOwnFunction)     
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
     File "ctypes.py", line 239, in __getattr__
       func = _StdcallFuncPtr(name, self)
   AttributeError: function 'MyOwnFunction' not found
   >>>

"kernel32" や "user32" のような win32 システム dll は、多くの場合関数
の UNICODE バージョンに加えて ANSI バージョンもエクスポートすることに
注意してください。 UNICODE バージョンは後ろに "W" が付いた名前でエクス
ポートされ、 ANSI バージョンは "A" が付いた名前でエクスポートされます
。与えられたモジュールの *モジュールハンドル* を返す win32
"GetModuleHandle" 関数は次のような C プロトタイプを持ちます。 UNICODE
バージョンが定義されているかどうかにより "GetModuleHandle" としてどち
らか一つを公開するためにマクロが使われます:

   /* ANSI version */
   HMODULE GetModuleHandleA(LPCSTR lpModuleName);
   /* UNICODE version */
   HMODULE GetModuleHandleW(LPCWSTR lpModuleName);

*windll* は魔法を使ってどちらか一つを選ぶようなことはしません。
"GetModuleHandleA" もしくは "GetModuleHandleW" を明示的に指定して必要
とするバージョンにアクセスし、バイト列か文字列を使ってそれぞれ呼び出さ
なければなりません。

時には、 dll が関数を ""??2@YAPAXI@Z"" のような Python 識別子として有
効でない名前でエクスポートすることがあります。このような場合に関数を取
り出すには、 "getattr()" を使わなければなりません。:

   >>> getattr(cdll.msvcrt, "??2@YAPAXI@Z")  
   <_FuncPtr object at 0x...>
   >>>

Windows では、名前ではなく序数によって関数をエクスポートする dll もあ
ります。こうした関数には序数を使って dll オブジェクトにインデックス指
定することでアクセスします:

   >>> cdll.kernel32[1]  
   <_FuncPtr object at 0x...>
   >>> cdll.kernel32[0]  
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
     File "ctypes.py", line 310, in __getitem__
       func = _StdcallFuncPtr(name, self)
   AttributeError: function ordinal 0 not found
   >>>


16.16.1.3. 関数を呼び出す
-------------------------

これらの関数は他の Python 呼び出し可能オブジェクトと同じように呼び出す
ことができます。この例では "time()" 関数 (Unixエポックからのシステム時
間を秒単位で返す) と、 "GetModuleHandleA()" 関数 (win32モジュールハン
ドルを返す) を使います。

この例は両方の関数を NULL ポインタとともに呼び出します ("None" を NULL
ポインタとして使う必要があります):

   >>> print(libc.time(None))  
   1150640792
   >>> print(hex(windll.kernel32.GetModuleHandleA(None)))  
   0x1d000000
   >>>

注釈:

  不正な数の引数が渡されたことを検知した場合、 "ctypes" は関数を呼び出
  した後に "ValueError" を送出することがあります。 この動作には依存す
  るべきではありません。 この動作は 3.6.2 で非推奨であり、 3.7 で削除
  予定です。

"cdecl" 呼び出し規約を使って "stdcall" 関数を呼び出したときには、
"ValueError" が送出されます。逆の場合も同様です:

   >>> cdll.kernel32.GetModuleHandleA(None)  
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   ValueError: Procedure probably called with not enough arguments (4 bytes missing)
   >>>

   >>> windll.msvcrt.printf(b"spam")  
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   ValueError: Procedure probably called with too many arguments (4 bytes in excess)
   >>>

正しい呼び出し規約を知るためには、呼び出したい関数についての C ヘッダ
ファイルもしくはドキュメントを見なければなりません。

Windows では、関数が無効な引数とともに呼び出された場合の一般保護例外に
よるクラッシュを防ぐために、 "ctypes" は win32 構造化例外処理を使いま
す:

   >>> windll.kernel32.GetModuleHandleA(32)  
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   OSError: exception: access violation reading 0x00000020
   >>>

しかしそれでも他に "ctypes" で Python がクラッシュする状況はあるので、
どちらにせよ気を配るべきです。クラッシュのデバッグには、
"faulthandler" モジュールが役に立つ場合があります (例えば、誤った C ラ
イブラリ呼び出しによって引き起こされたセグメンテーション違反) 。

"None" 、整数、バイト列オブジェクトおよび (Unicode) 文字列だけが、こう
した関数呼び出しにおいてパラメータとして直接使えるネイティブの Python
オブジェクトです。 "None" は C の "NULL" ポインタとして渡され、バイト
文字列とユニコード文字列はそのデータを含むメモリブロックへのポインタ
("char *" または "wchar_t *") として渡されます。 Python 整数はプラット
ホームのデフォルトの C "int" 型として渡され、その値は C "int" 型に合う
ようにマスクされます。

他のパラメータ型をもつ関数呼び出しに移る前に、 "ctypes" データ型につい
てさらに学ぶ必要があります。


16.16.1.4. 基本データ型
-----------------------

"ctypes" ではいくつもの C 互換のプリミティブなデータ型を定義しています
:

+------------------------+--------------------------------------------+------------------------------+
| ctypes の型            | C の型                                     | Python の型                  |
|========================|============================================|==============================|
| "c_bool"               | "_Bool"                                    | bool (1)                     |
+------------------------+--------------------------------------------+------------------------------+
| "c_char"               | "char"                                     | 1文字のバイト列オブジェクト  |
+------------------------+--------------------------------------------+------------------------------+
| "c_wchar"              | "wchar_t"                                  | 1文字の文字列                |
+------------------------+--------------------------------------------+------------------------------+
| "c_byte"               | "char"                                     | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_ubyte"              | "unsigned char"                            | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_short"              | "short"                                    | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_ushort"             | "unsigned short"                           | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_int"                | "int"                                      | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_uint"               | "unsigned int"                             | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_long"               | "long"                                     | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_ulong"              | "unsigned long"                            | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_longlong"           | "__int64" または "long long"               | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_ulonglong"          | "unsigned __int64" または "unsigned long   | int                          |
|                        | long"                                      |                              |
+------------------------+--------------------------------------------+------------------------------+
| "c_size_t"             | "size_t"                                   | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_ssize_t"            | "ssize_t" または "Py_ssize_t"              | int                          |
+------------------------+--------------------------------------------+------------------------------+
| "c_float"              | "float"                                    | 浮動小数点数                 |
+------------------------+--------------------------------------------+------------------------------+
| "c_double"             | "double"                                   | 浮動小数点数                 |
+------------------------+--------------------------------------------+------------------------------+
| "c_longdouble"         | "long double"                              | 浮動小数点数                 |
+------------------------+--------------------------------------------+------------------------------+
| "c_char_p"             | "char *" (NUL 終端)                        | バイト列オブジェクトまたは   |
|                        |                                            | "None"                       |
+------------------------+--------------------------------------------+------------------------------+
| "c_wchar_p"            | "wchar_t *" (NUL 終端)                     | 文字列または "None"          |
+------------------------+--------------------------------------------+------------------------------+
| "c_void_p"             | "void *"                                   | 整数または "None"            |
+------------------------+--------------------------------------------+------------------------------+

1. コンストラクタは任意のオブジェクトをその真偽値として受け取ります。

これら全ての型はその型を呼び出すことによって作成でき、オプションとして
型と値が合っている初期化子を指定することができます:

   >>> c_int()
   c_long(0)
   >>> c_wchar_p("Hello, World")
   c_wchar_p(140018365411392)
   >>> c_ushort(-3)
   c_ushort(65533)
   >>>

これらの型は変更可能であり、値を後で変更することもできます:

   >>> i = c_int(42)
   >>> print(i)
   c_long(42)
   >>> print(i.value)
   42
   >>> i.value = -99
   >>> print(i.value)
   -99
   >>>

新しい値をポインタ型 "c_char_p", "c_wchar_p" および "c_void_p" のイン
スタンスへ代入すると、変わるのは指している *メモリ位置* であって、メモ
リブロックの *内容ではありません* (これは当然で、なぜなら、 Python バ
イト列オブジェクトは変更不可能だからです):

   >>> s = "Hello, World"
   >>> c_s = c_wchar_p(s)
   >>> print(c_s)
   c_wchar_p(139966785747344)
   >>> print(c_s.value)
   Hello World
   >>> c_s.value = "Hi, there"
   >>> print(c_s)              # the memory location has changed
   c_wchar_p(139966783348904)
   >>> print(c_s.value)
   Hi, there
   >>> print(s)                # first object is unchanged
   Hello, World
   >>>

しかし、変更可能なメモリを指すポインタであることを想定している関数へそ
れらを渡さないように注意すべきです。もし変更可能なメモリブロックが必要
なら、 ctypes には "create_string_buffer()" 関数があり、いろいろな方法
で作成することできます。現在のメモリブロックの内容は "raw" プロパティ
を使ってアクセス (あるいは変更) することができます。もし現在のメモリブ
ロックに NUL 終端文字列としてアクセスしたいなら、 "value" プロパティを
使ってください:

   >>> from ctypes import *
   >>> p = create_string_buffer(3)            # create a 3 byte buffer, initialized to NUL bytes
   >>> print(sizeof(p), repr(p.raw))
   3 b'\x00\x00\x00'
   >>> p = create_string_buffer(b"Hello")     # create a buffer containing a NUL terminated string
   >>> print(sizeof(p), repr(p.raw))
   6 b'Hello\x00'
   >>> print(repr(p.value))
   b'Hello'
   >>> p = create_string_buffer(b"Hello", 10) # create a 10 byte buffer
   >>> print(sizeof(p), repr(p.raw))
   10 b'Hello\x00\x00\x00\x00\x00'
   >>> p.value = b"Hi"
   >>> print(sizeof(p), repr(p.raw))
   10 b'Hi\x00lo\x00\x00\x00\x00\x00'
   >>>

"create_string_buffer()" 関数は初期の ctypes リリースにあった
"c_string()" 関数だけでなく、 (エイリアスとしてはまだ利用できる)
"c_buffer()" 関数をも置き換えるものです。 C の型 "wchar_t" の Unicode
文字を含む変更可能なメモリブロックを作成するには、
"create_unicode_buffer()" 関数を使ってください。


16.16.1.5. 続・関数を呼び出す
-----------------------------

printf は "sys.stdout" では *なく* 、本物の標準出力チャンネルへプリン
トすることに注意してください。したがって、これらの例はコンソールプロン
プトでのみ動作し、 *IDLE* や *PythonWin* では動作しません。:

   >>> printf = libc.printf
   >>> printf(b"Hello, %s\n", b"World!")
   Hello, World!
   14
   >>> printf(b"Hello, %S\n", "World!")
   Hello, World!
   14
   >>> printf(b"%d bottles of beer\n", 42)
   42 bottles of beer
   19
   >>> printf(b"%f bottles of beer\n", 42.5)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   ArgumentError: argument 2: exceptions.TypeError: Don't know how to convert parameter 2
   >>>

前に述べたように、必要な C のデータ型へ変換できるようにするためには、
整数、文字列およびバイト列オブジェクトを除くすべての Python 型を対応す
る "ctypes" 型でラップしなければなりません:

   >>> printf(b"An int %d, a double %f\n", 1234, c_double(3.14))
   An int 1234, a double 3.140000
   31
   >>>


16.16.1.6. 自作のデータ型とともに関数を呼び出す
-----------------------------------------------

自作のクラスのインスタンスを関数引数として使えるように、 "ctypes" 引数
変換をカスタマイズすることもできます。 "ctypes" は "_as_parameter_" 属
性を探し出し、関数引数として使います。もちろん、整数、文字列もしくはバ
イト列オブジェクトの中の一つでなければなりません:

   >>> class Bottles:
   ...     def __init__(self, number):
   ...         self._as_parameter_ = number
   ...
   >>> bottles = Bottles(42)
   >>> printf(b"%d bottles of beer\n", bottles)
   42 bottles of beer
   19
   >>>

"_as_parameter_" インスタンス変数にインスタンスのデータを保持したくな
い場合は、必要に応じて利用できる属性を作る "property" を定義しても構い
ません。


16.16.1.7. 要求される引数の型を指定する (関数プロトタイプ)
----------------------------------------------------------

"argtypes" 属性を設定することによって、 DLL からエクスポートされている
関数に要求される引数の型を指定することができます。

"argtypes" は C データ型のシーケンスでなければなりません (この場合
"printf" 関数はおそらく良い例ではありません。なぜなら、引数の数が可変
であり、フォーマット文字列に依存した異なる型のパラメータを取るからです
。一方では、この機能の実験にはとても便利です)。:

   >>> printf.argtypes = [c_char_p, c_char_p, c_int, c_double]
   >>> printf(b"String '%s', Int %d, Double %f\n", b"Hi", 10, 2.2)
   String 'Hi', Int 10, Double 2.200000
   37
   >>>

(C の関数のプロトタイプのように) 書式を指定すると互換性のない引数型に
なるのを防ぎ、引数を有効な型へ変換しようとします。:

   >>> printf(b"%d %d %d", 1, 2, 3)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   ArgumentError: argument 2: exceptions.TypeError: wrong type
   >>> printf(b"%s %d %f\n", b"X", 2, 3)
   X 2 3.000000
   13
   >>>

関数呼び出しへ渡す自作のクラスを定義した場合には、 "argtypes" シーケン
スの中で使えるようにするために、そのクラスに "from_param()" クラスメソ
ッドを実装しなければなりません。 "from_param()" クラスメソッドは関数呼
び出しへ渡された Python オブジェクトを受け取り、型チェックもしくはこの
オブジェクトが受け入れ可能であると確かめるために必要なことはすべて行っ
てから、オブジェクト自身、 "_as_parameter_" 属性、あるいは、この場合に
C 関数引数として渡したい何かの値を返さなければなりません。繰り返しにな
りますが、その返される結果は整数、文字列、バイト列、 "ctypes" インスタ
ンス、あるいは "_as_parameter_" 属性をもつオブジェクトであるべきです。


16.16.1.8. 戻り値の型
---------------------

デフォルトでは、関数は C "int" を返すと仮定されます。他の戻り値の型を
指定するには、関数オブジェクトの "restype" 属性に設定します。

さらに高度な例として、 "strchr" 関数を使います。この関数は文字列ポイン
タと char を受け取り、文字列へのポインタを返します。:

   >>> strchr = libc.strchr
   >>> strchr(b"abcdef", ord("d"))  
   8059983
   >>> strchr.restype = c_char_p    # c_char_p is a pointer to a string
   >>> strchr(b"abcdef", ord("d"))
   b'def'
   >>> print(strchr(b"abcdef", ord("x")))
   None
   >>>

上の "ord("x")" 呼び出しを避けたいなら、 "argtypes" 属性を設定すること
ができます。二番目の引数が一文字の Python バイト列オブジェクトから C
の char へ変換されます:

   >>> strchr.restype = c_char_p
   >>> strchr.argtypes = [c_char_p, c_char]
   >>> strchr(b"abcdef", b"d")
   'def'
   >>> strchr(b"abcdef", b"def")
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   ArgumentError: argument 2: exceptions.TypeError: one character string expected
   >>> print(strchr(b"abcdef", b"x"))
   None
   >>> strchr(b"abcdef", b"d")
   'def'
   >>>

外部関数が整数を返す場合は、 "restype" 属性として呼び出し可能な Python
オブジェクト (例えば、関数またはクラス) を使うこともできます。呼び出し
可能オブジェクトは C 関数が返す *整数* とともに呼び出され、この呼び出
しの結果は関数呼び出しの結果として使われるでしょう。これはエラーの戻り
値をチェックして自動的に例外を送出させるために役に立ちます。:

   >>> GetModuleHandle = windll.kernel32.GetModuleHandleA  
   >>> def ValidHandle(value):
   ...     if value == 0:
   ...         raise WinError()
   ...     return value
   ...
   >>>
   >>> GetModuleHandle.restype = ValidHandle  
   >>> GetModuleHandle(None)  
   486539264
   >>> GetModuleHandle("something silly")  
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
     File "<stdin>", line 3, in ValidHandle
   OSError: [Errno 126] The specified module could not be found.
   >>>

"WinError" はエラーコードの文字列表現を得るために Windows の
"FormatMessage()" api を呼び出し、例外を *返す* 関数です。 "WinError"
はオプションでエラーコードパラメータを取ります。このパラメータが使われ
ない場合は、エラーコードを取り出すために "GetLastError()" を呼び出しま
す。

"errcheck" 属性によってもっと強力なエラーチェック機構を利用できること
に注意してください。詳細はリファレンスマニュアルを参照してください。


16.16.1.9. ポインタを渡す(または、パラメータの参照渡し)
-------------------------------------------------------

時には、 C api 関数がパラメータのデータ型として *ポインタ* を想定して
いることがあります。おそらくパラメータと同一の場所に書き込むためか、も
しくはそのデータが大きすぎて値渡しできない場合です。これは *パラメータ
の参照渡し* としても知られています。

"ctypes" は "byref()" 関数をエクスポートしており、パラメータを参照渡し
するために使用します。 "pointer()" 関数を使っても同じ効果が得られます
。しかし、 "pointer()" は本当のポインタオブジェクトを構築するためより
多くの処理を行うことから、 Python 側でポインタオブジェクト自体を必要と
しないならば "byref()" を使う方がより高速です。:

   >>> i = c_int()
   >>> f = c_float()
   >>> s = create_string_buffer(b'\000' * 32)
   >>> print(i.value, f.value, repr(s.value))
   0 0.0 b''
   >>> libc.sscanf(b"1 3.14 Hello", b"%d %f %s",
   ...             byref(i), byref(f), s)
   3
   >>> print(i.value, f.value, repr(s.value))
   1 3.1400001049 b'Hello'
   >>>


16.16.1.10. 構造体と共用体
--------------------------

構造体と共用体は "ctypes" モジュールに定義されている "Structure" およ
び "Union" ベースクラスからの派生クラスでなければなりません。それぞれ
のサブクラスは "_fields_" 属性を定義する必要があります。 "_fields_" は
*フィールド名* と *フィールド型* を持つ *2要素タプル* のリストでなけれ
ばなりません。

フィールド型は "c_int" か他の "ctypes" 型 (構造体、共用体、配列、ポイ
ンタ) から派生した "ctypes" 型である必要があります。

以下は、 *x* と *y* という名前の二つの整数からなる簡単な POINT 構造体
の例です。コンストラクタで構造体を初期化する方法も説明しています:

   >>> from ctypes import *
   >>> class POINT(Structure):
   ...     _fields_ = [("x", c_int),
   ...                 ("y", c_int)]
   ...
   >>> point = POINT(10, 20)
   >>> print(point.x, point.y)
   10 20
   >>> point = POINT(y=5)
   >>> print(point.x, point.y)
   0 5
   >>> POINT(1, 2, 3)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   ValueError: too many initializers
   >>>

しかし、もっと複雑な構造体を構築することもできます。ある構造体は、他の
構造体をフィールド型として使うことで、他の構造体を含むことができます。

*upperleft* と *lowerright* という名前の二つの POINT を持つ RECT 構造
体です。:

   >>> class RECT(Structure):
   ...     _fields_ = [("upperleft", POINT),
   ...                 ("lowerright", POINT)]
   ...
   >>> rc = RECT(point)
   >>> print(rc.upperleft.x, rc.upperleft.y)
   0 5
   >>> print(rc.lowerright.x, rc.lowerright.y)
   0 0
   >>>

入れ子になった構造体はいくつかの方法を用いてコンストラクタで初期化する
ことができます。:

   >>> r = RECT(POINT(1, 2), POINT(3, 4))
   >>> r = RECT((1, 2), (3, 4))

フィールド *descriptor* (記述子)は *クラス* から取り出せます。デバッグ
するときに役に立つ情報を得ることができます:

   >>> print(POINT.x)
   <Field type=c_long, ofs=0, size=4>
   >>> print(POINT.y)
   <Field type=c_long, ofs=4, size=4>
   >>>

警告:

  "ctypes" では、ビットフィールドのある共用体や構造体の関数への値渡し
  はサポートしていません。これは 32-bit の x86 環境では動くかもしれま
  せんが、このライブラリでは一般の場合に動作することは保証していません
  。


16.16.1.11. 構造体/共用体アライメントとバイトオーダー
-----------------------------------------------------

デフォルトでは、構造体 (Structure) と共用体(Union) のフィールドは C コ
ンパイラが行うのと同じ方法でアライメントされています。サブクラスを定義
するときに "_pack_" クラス属性を指定することでこの動作を変えることは可
能です。このクラス属性には正の整数を設定する必要があり、フィールドの最
大アライメントを指定します。これは MSVC で "#pragma pack(n)" が行って
いること同じです。

"ctypes" は Structure と Union に対してネイティブのバイトオーダーを使
います。ネイティブではないバイトオーダーの構造体を作成するには、
"BigEndianStructure", "LittleEndianStructure", "BigEndianUnion" および
"LittleEndianUnion" ベースクラスの中の一つを使います。これらのクラスに
ポインタフィールドを持たせることはできません。


16.16.1.12. 構造体と共用体におけるビットフィールド
--------------------------------------------------

ビットフィールドを含む構造体と共用体を作ることができます。ビットフィー
ルドは整数フィールドに対してのみ作ることができ、ビット幅は "_fields_"
タプルの第三要素で指定します。:

   >>> class Int(Structure):
   ...     _fields_ = [("first_16", c_int, 16),
   ...                 ("second_16", c_int, 16)]
   ...
   >>> print(Int.first_16)
   <Field type=c_long, ofs=0:0, bits=16>
   >>> print(Int.second_16)
   <Field type=c_long, ofs=0:16, bits=16>
   >>>


16.16.1.13. 配列
----------------

配列 (Array) はシーケンスであり、決まった数の同じ型のインスタンスを持
ちます。

推奨されている配列の作成方法はデータ型に正の整数を掛けることです。:

   TenPointsArrayType = POINT * 10

ややわざとらしいデータ型の例になりますが、他のものに混ざって 4 個の
POINT がある構造体です:

   >>> from ctypes import *
   >>> class POINT(Structure):
   ...     _fields_ = ("x", c_int), ("y", c_int)
   ...
   >>> class MyStruct(Structure):
   ...     _fields_ = [("a", c_int),
   ...                 ("b", c_float),
   ...                 ("point_array", POINT * 4)]
   >>>
   >>> print(len(MyStruct().point_array))
   4
   >>>

インスタンスはクラスを呼び出す通常の方法で作成します。:

   arr = TenPointsArrayType()
   for pt in arr:
       print(pt.x, pt.y)

上記のコードは "0 0" という行が並んだものを表示します。配列の要素がゼ
ロで初期化されているためです。

正しい型の初期化子を指定することもできます。:

   >>> from ctypes import *
   >>> TenIntegers = c_int * 10
   >>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
   >>> print(ii)
   <c_long_Array_10 object at 0x...>
   >>> for i in ii: print(i, end=" ")
   ...
   1 2 3 4 5 6 7 8 9 10
   >>>


16.16.1.14. ポインタ
--------------------

ポインタのインスタンスは "ctypes" 型に対して "pointer()" 関数を呼び出
して作成します。:

   >>> from ctypes import *
   >>> i = c_int(42)
   >>> pi = pointer(i)
   >>>

次のように、ポインタインスタンスは、ポインタが指すオブジェクト (上の例
では "i") を返す "contents" 属性を持ちます:

   >>> pi.contents
   c_long(42)
   >>>

"ctypes" は OOR (original object return 、元のオブジェクトを返すこと)
ではないことに注意してください。属性を取り出す度に、新しい同等のオブジ
ェクトを作成しているのです。:

   >>> pi.contents is i
   False
   >>> pi.contents is pi.contents
   False
   >>>

別の "c_int" インスタンスがポインタの contents 属性に代入されると、こ
れが記憶されているメモリ位置を指すポインタに変化します。:

   >>> i = c_int(99)
   >>> pi.contents = i
   >>> pi.contents
   c_long(99)
   >>>

ポインタインスタンスは整数でインデックス指定することもできます。:

   >>> pi[0]
   99
   >>>

整数インデックスへ代入するとポインタが指す値が変更されます。:

   >>> print(i)
   c_long(99)
   >>> pi[0] = 22
   >>> print(i)
   c_long(22)
   >>>

0 ではないインデックスを使うこともできますが、 C の場合と同じように自
分が何をしているかを理解している必要があります。任意のメモリ位置にアク
セスもしくは変更できるのです。一般的にこの機能を使うのは、 C 関数から
ポインタを受け取り、そのポインタが単一の要素ではなく実際に配列を指して
いると *分かっている* 場合だけです。

舞台裏では、 "pointer()" 関数は単にポインタインスタンスを作成するとい
う以上のことを行っています。はじめにポインタ *型* を作成する必要があり
ます。これは任意の "ctypes" 型を受け取る "POINTER()" 関数を使って行わ
れ、新しい型を返します:

   >>> PI = POINTER(c_int)
   >>> PI
   <class 'ctypes.LP_c_long'>
   >>> PI(42)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: expected c_long instead of int
   >>> PI(c_int(42))
   <ctypes.LP_c_long object at 0x...>
   >>>

ポインタ型を引数なしで呼び出すと "NULL" ポインタを作成します。 "NULL"
ポインタは "False" ブール値を持っています。:

   >>> null_ptr = POINTER(c_int)()
   >>> print(bool(null_ptr))
   False
   >>>

"ctypes" はポインタの指す値を取り出すときに "NULL" かどうかを調べます(
しかし、 "NULL" でない不正なポインタの指す値の取り出す行為は Python を
クラッシュさせるでしょう)。:

   >>> null_ptr[0]
   Traceback (most recent call last):
       ....
   ValueError: NULL pointer access
   >>>

   >>> null_ptr[0] = 1234
   Traceback (most recent call last):
       ....
   ValueError: NULL pointer access
   >>>


16.16.1.15. 型変換
------------------

たいていの場合、 ctypes は厳密な型チェックを行います。これが意味するの
は、関数の "argtypes" リスト内に、もしくは、構造体定義におけるメンバー
フィールドの型として "POINTER(c_int)" がある場合、厳密に同じ型のインス
タンスだけを受け取るということです。このルールには ctypes が他のオブジ
ェクトを受け取る場合に例外がいくつかあります。例えば、ポインタ型の代わ
りに互換性のある配列インスタンスを渡すことができます。このように、
"POINTER(c_int)" に対して、 ctypes は c_int の配列を受け取ります。:

   >>> class Bar(Structure):
   ...     _fields_ = [("count", c_int), ("values", POINTER(c_int))]
   ...
   >>> bar = Bar()
   >>> bar.values = (c_int * 3)(1, 2, 3)
   >>> bar.count = 3
   >>> for i in range(bar.count):
   ...     print(bar.values[i])
   ...
   1
   2
   3
   >>>

それに加えて、 "argtypes" で関数の引数が明示的に ("POINTER(c_int)" な
どの) ポインタ型であると宣言されていた場合、ポインタ型が指し示している
型のオブジェクト (この場合では "c_int") を関数に渡すことができます。こ
の場合 ctypes は、必要となる "byref()" での変換を自動的に適用します。

POINTER型フィールドを "NULL" に設定するために、 "None" を代入してもか
まいません。:

   >>> bar.values = None
   >>>

時には、非互換な型のインスタンスであることもあります。 C では、ある型
を他の型へキャストすることができます。 "ctypes" は同じやり方で使える
"cast()" 関数を提供しています。上で定義した "Bar" 構造体は
"POINTER(c_int)" ポインタまたは "c_int" 配列を "values" フィールドに対
して受け取り、他の型のインスタンスは受け取りません:

   >>> bar.values = (c_byte * 4)()
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: incompatible types, c_byte_Array_4 instance instead of LP_c_long instance
   >>>

このような場合には、 "cast()" 関数が便利です。

"cast()" 関数は ctypes インスタンスを異なる ctypes データ型を指すポイ
ンタへキャストするために使えます。 "cast()" は二つのパラメータ、ある種
のポインタかそのポインタへ変換できる ctypes オブジェクトと、 ctypes ポ
インタ型を取ります。そして、第二引数のインスタンスを返します。このイン
スタンスは第一引数と同じメモリブロックを参照しています:

   >>> a = (c_byte * 4)()
   >>> cast(a, POINTER(c_int))
   <ctypes.LP_c_long object at ...>
   >>>

したがって、 "cast()" を "Bar" 構造体の "values" フィールドへ代入する
ために使うことができます:

   >>> bar = Bar()
   >>> bar.values = cast((c_byte * 4)(), POINTER(c_int))
   >>> print(bar.values[0])
   0
   >>>


16.16.1.16. 不完全型
--------------------

*不完全型* はメンバーがまだ指定されていない構造体、共用体もしくは配列
です。 C では、前方宣言により指定され、後で定義されます。:

   struct cell; /* forward declaration */

   struct cell {
       char *name;
       struct cell *next;
   };

ctypes コードへの直接的な変換ではこうなるでしょう。しかし、動作しませ
ん:

   >>> class cell(Structure):
   ...     _fields_ = [("name", c_char_p),
   ...                 ("next", POINTER(cell))]
   ...
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
     File "<stdin>", line 2, in cell
   NameError: name 'cell' is not defined
   >>>

なぜなら、新しい "class cell" はクラス文自体の中では利用できないからで
す。 "ctypes" では、 "cell" クラスを定義して、 "_fields_" 属性をクラス
文の後で設定することができます。:

   >>> from ctypes import *
   >>> class cell(Structure):
   ...     pass
   ...
   >>> cell._fields_ = [("name", c_char_p),
   ...                  ("next", POINTER(cell))]
   >>>

試してみましょう。 "cell" のインスタンスを二つ作り、互いに参照し合うよ
うにします。最後に、つながったポインタを何度かたどります。:

   >>> c1 = cell()
   >>> c1.name = "foo"
   >>> c2 = cell()
   >>> c2.name = "bar"
   >>> c1.next = pointer(c2)
   >>> c2.next = pointer(c1)
   >>> p = c1
   >>> for i in range(8):
   ...     print(p.name, end=" ")
   ...     p = p.next[0]
   ...
   foo bar foo bar foo bar foo bar
   >>>


16.16.1.17. コールバック関数
----------------------------

"ctypes" は C の呼び出し可能な関数ポインタを Python 呼び出し可能オブジ
ェクトから作成できるようにします。これらは *コールバック関数* と呼ばれ
ることがあります。

最初に、コールバック関数のためのクラスを作る必要があります。そのクラス
には呼び出し規約、戻り値の型およびこの関数が受け取る引数の数と型につい
ての情報があります。

"CFUNCTYPE()" ファクトリ関数は通常の "cdecl" 呼び出し規約を用いてコー
ルバック関数のための型を作成します。 Windows では、 "WINFUNCTYPE()" フ
ァクトリ関数が "stdcall" 呼び出し規約を用いてコールバック関数の型を作
成します。

これらのファクトリ関数はともに最初の引数に戻り値の型、残りの引数として
コールバック関数が想定する引数の型を渡して呼び出されます。

標準 C ライブラリの "qsort()" 関数を使う例を示します。これはコールバッ
ク関数の助けをかりて要素をソートするために使われます。 "qsort()" は整
数の配列をソートするために使われます:

   >>> IntArray5 = c_int * 5
   >>> ia = IntArray5(5, 1, 7, 33, 99)
   >>> qsort = libc.qsort
   >>> qsort.restype = None
   >>>

"qsort()" はソートするデータを指すポインタ、データ配列の要素の数、要素
の一つの大きさ、およびコールバック関数である比較関数へのポインタを引数
に渡して呼び出さなければなりません。そして、コールバック関数は要素を指
す二つのポインタを渡されて呼び出され、一番目が二番目より小さいなら負の
数を、等しいならゼロを、それ以外なら正の数を返さなければなりません。

コールバック関数は整数へのポインタを受け取り、整数を返す必要があります
。まず、コールバック関数のための "type" を作成します。:

   >>> CMPFUNC = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
   >>>

まず初めに、これが受け取った変数を表示するだけのシンプルなコールバック
です:

   >>> def py_cmp_func(a, b):
   ...     print("py_cmp_func", a[0], b[0])
   ...     return 0
   ...
   >>> cmp_func = CMPFUNC(py_cmp_func)
   >>>

結果は以下の通りです:

   >>> qsort(ia, len(ia), sizeof(c_int), cmp_func)  
   py_cmp_func 5 1
   py_cmp_func 33 99
   py_cmp_func 7 33
   py_cmp_func 5 7
   py_cmp_func 1 7
   >>>

ここで 2 つの要素を実際に比較し、役に立つ結果を返します:

   >>> def py_cmp_func(a, b):
   ...     print("py_cmp_func", a[0], b[0])
   ...     return a[0] - b[0]
   ...
   >>>
   >>> qsort(ia, len(ia), sizeof(c_int), CMPFUNC(py_cmp_func)) 
   py_cmp_func 5 1
   py_cmp_func 33 99
   py_cmp_func 7 33
   py_cmp_func 1 7
   py_cmp_func 5 7
   >>>

簡単に確認できるように、配列を次のようにソートしました:

   >>> for i in ia: print(i, end=" ")
   ...
   1 5 7 33 99
   >>>

関数ファクトリはデコレータファクトリとしても使えるので、次のようにも書
けます:

   >>> @CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
   ... def py_cmp_func(a, b):
   ...     print("py_cmp_func", a[0], b[0])
   ...     return a[0] - b[0]
   ...
   >>> qsort(ia, len(ia), sizeof(c_int), py_cmp_func)
   py_cmp_func 5 1
   py_cmp_func 33 99
   py_cmp_func 7 33
   py_cmp_func 1 7
   py_cmp_func 5 7
   >>>

注釈:

  C コードから "CFUNCTYPE()" オブジェクトが使用される限り、そのオブジ
  ェクトへの参照を確実に保持してください。 "ctypes" は参照を保持しない
  ため、あなたが参照を保持しないと、オブジェクトはガベージコレクション
  の対象となり、コールバックが行われたときにプログラムをクラッシュさせ
  る場合があります。同様に、コールバック関数が Python の管理外 (例えば
  、コールバックを呼び出す外部のコード) で作られたスレッドで呼び出され
  た場合、 ctypes は全ての呼び出しごとに新しいダミーの Python スレッド
  を作成することに注意してください。 この動作はほとんどの目的に対して
  正しいものですが、同じ C スレッドからの呼び出しだったとしても、
  "threading.local" で格納された値は異なるコールバックをまたいで生存は
  *しません* 。


16.16.1.18. 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" ポインタにアクセスします。

この値のドキュメントから引用すると:

   このポインタは "struct _frozen" のレコードからなり、終端の要素のメ
   ンバが *NULL* かゼロになっているような配列を指すよう初期化されます
   。フリーズされたモジュールをインポートするとき、このテーブルを検索
   します。サードパーティ製のコードからこのポインタに仕掛けを講じて、
   動的に生成されたフリーズ化モジュールの集合を提供するようにできます
   。

これで、このポインタを操作することが役に立つことを証明できるでしょう。
例の大きさを制限するために、このテーブルを "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:
   ...     if item.name is None:
   ...         break
   ...     print(item.name.decode("ascii"), item.size)
   ...
   _frozen_importlib 31764
   _frozen_importlib_external 41499
   __hello__ 161
   __phello__ -161
   __phello__.spam 161
   >>>

標準 Python はフローズンモジュールとフローズンパッケージ (負のサイズの
メンバーで表されています) を持っているという事実はあまり知られておらず
、テストにだけ使われています。例えば、 "import __hello__" を試してみて
ください。


16.16.1.19. びっくり仰天
------------------------

There are some edges in "ctypes" where you might expect something
other than what actually happens.

次に示す例について考えてみてください。:

   >>> from ctypes import *
   >>> class POINT(Structure):
   ...     _fields_ = ("x", c_int), ("y", c_int)
   ...
   >>> class RECT(Structure):
   ...     _fields_ = ("a", POINT), ("b", POINT)
   ...
   >>> p1 = POINT(1, 2)
   >>> p2 = POINT(3, 4)
   >>> rc = RECT(p1, p2)
   >>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
   1 2 3 4
   >>> # now swap the two points
   >>> rc.a, rc.b = rc.b, rc.a
   >>> print(rc.a.x, rc.a.y, rc.b.x, rc.b.y)
   3 4 3 4
   >>>

うーん、最後の文に "3 4 1 2" と表示されることを期待していたはずです。
何が起きたのでしょうか? 上の行の "rc.a, rc.b = rc.b, rc.a" の各段階は
このようになります。:

   >>> temp0, temp1 = rc.b, rc.a
   >>> rc.a = temp0
   >>> rc.b = temp1
   >>>

"temp0" と "temp1" は前記の "rc" オブジェクトの内部バッファでまだ使わ
れているオブジェクトです。したがって、 "rc.a = temp0" を実行すると
"temp0" のバッファ内容が "rc" のバッファへコピーされます。さらに、これ
は "temp1" の内容を変更します。そのため、最後の代入 "rc.b = temp1" は
、期待する結果にはならないのです。

Structure 、 Union および Array のサブオブジェクトを取り出しても、その
サブオブジェクトが *コピー* されるわけではなく、ルートオブジェクトの内
部バッファにアクセスするラッパーオブジェクトを取り出すことを覚えておい
てください。

期待とは違う振る舞いをする別の例はこれです。:

   >>> s = c_char_p()
   >>> s.value = "abc def ghi"
   >>> s.value
   'abc def ghi'
   >>> s.value is s.value
   False
   >>>

なぜ "False" と表示されるのでしょうか? ctypes インスタンスはメモリと、
メモリの内容にアクセスするいくつかの *descriptor* (記述子)を含むオブジ
ェクトです。メモリブロックに Python オブジェクトを保存してもオブジェク
ト自身が保存される訳ではなく、オブジェクトの "contents" が保存されます
。その contents に再アクセスすると新しい Python オブジェクトがその度に
作られます。


16.16.1.20. 可変サイズのデータ型
--------------------------------

"ctypes" は可変サイズの配列と構造体をサポートしています。

"resize()" 関数は既存の ctypes オブジェクトのメモリバッファのサイズを
変更したい場合に使えます。この関数は第一引数にオブジェクト、第二引数に
要求されたサイズをバイト単位で指定します。メモリブロックはオブジェクト
型で指定される通常のメモリブロックより小さくすることはできません。これ
をやろうとすると、 "ValueError" が送出されます。:

   >>> short_array = (c_short * 4)()
   >>> print(sizeof(short_array))
   8
   >>> resize(short_array, 4)
   Traceback (most recent call last):
       ...
   ValueError: minimum size is 8
   >>> resize(short_array, 32)
   >>> sizeof(short_array)
   32
   >>> sizeof(type(short_array))
   8
   >>>

これはこれで上手くいっていますが、この配列の追加した要素へどうやってア
クセスするのでしょうか? この型は要素の数が 4 個であるとまだ認識してい
るので、他の要素にアクセスするとエラーになります。:

   >>> short_array[:]
   [0, 0, 0, 0]
   >>> short_array[7]
   Traceback (most recent call last):
       ...
   IndexError: invalid index
   >>>

"ctypes" で可変サイズのデータ型を使うもう一つの方法は、必要なサイズが
分かった後に Python の動的性質を使って一つ一つデータ型を(再)定義するこ
とです。


16.16.2. ctypesリファレンス
===========================


16.16.2.1. 共有ライブラリを見つける
-----------------------------------

コンパイルされる言語でプログラミングしている場合、共有ライブラリはプロ
グラムをコンパイル/リンクしているときと、そのプログラムが動作している
ときにアクセスされます。

ctypes ライブラリローダーはプログラムが動作しているときのように振る舞
い、ランタイムローダーを直接呼び出すのに対し、 "find_library()" 関数の
目的はコンパイラまたはランタイムローダーが行うのと似た方法でライブラリ
を探し出すことです。 (複数のバージョンの共有ライブラリがあるプラットホ
ームでは、一番最近に見つかったものがロードされます)。

"ctypes.util" モジュールはロードするライブラリを決めるのに役立つ関数を
提供します。

ctypes.util.find_library(name)

   ライブラリを見つけてパス名を返そうと試みます。 *name* は "lib" のよ
   うな接頭辞、 ".so", ".dylib" のような接尾辞、あるいは、バージョン番
   号が何も付いていないライブラリの名前です (これは posix リンカのオプ
   ション "-l" に使われている形式です)。 ライブラリが見つからないとき
   は "None" を返します。

厳密な機能はシステムに依存します。

Linux では、 "find_library()" はライブラリファイルを見つけるために外部
プログラム ("/sbin/ldconfig", "gcc", "objdump" と "ld") を実行しようと
します。ライブラリファイルのファイル名を返します。

バージョン 3.6 で変更: Linux では、ライブラリを検索する際に、他の方法
でライブラリが見つけられない場合は、 "LD_LIBRARY_PATH" 環境変数の値が
使われます

ここに例があります:

   >>> from ctypes.util import find_library
   >>> find_library("m")
   'libm.so.6'
   >>> find_library("c")
   'libc.so.6'
   >>> find_library("bz2")
   'libbz2.so.1.0'
   >>>

OS X では、 "find_library()" はライブラリの位置を探すために、予め定義
された複数の命名方法とパスを試し、成功すればフルパスを返します。:

   >>> from ctypes.util import find_library
   >>> find_library("c")
   '/usr/lib/libc.dylib'
   >>> find_library("m")
   '/usr/lib/libm.dylib'
   >>> find_library("bz2")
   '/usr/lib/libbz2.dylib'
   >>> find_library("AGL")
   '/System/Library/Frameworks/AGL.framework/AGL'
   >>>

Windows では、 "find_library()" はシステムの探索パスに沿って探し、フル
パスを返します。しかし、予め定義された命名方法がないため、
"find_library("c")" のような呼び出しは失敗し、 "None" を返します。

"ctypes" で共有ライブラリをラップする場合、 "find_library()" を使って
実行時にライブラリの場所を特定するのではなく、共有ライブラリの名前を開
発時に決めておいて、ラッパーモジュールにハードコードする方が良い *かも
しれません* 。


16.16.2.2. 共有ライブラリをロードする
-------------------------------------

共有ライブラリを Python プロセスへロードする方法はいくつかあります。一
つの方法は下記のクラスの一つをインスタンス化することです:

class ctypes.CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)

   このクラスのインスタンスはロードされた共有ライブラリをあらわします
   。これらのライブラリの関数は標準 C 呼び出し規約を使用し、 "int" を
   返すと仮定されます。

class ctypes.OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)

   Windows 用: このクラスのインスタンスはロードされた共有ライブラリを
   あらわします。これらのライブラリの関数は "stdcall" 呼び出し規約を使
   用し、 windows 固有の "HRESULT" コードを返すと仮定されます。
   "HRESULT" 値には関数呼び出しが失敗したのか成功したのかを特定する情
   報とともに、補足のエラーコードが含まれます。戻り値が失敗を知らせた
   ならば、 "OSError" が自動的に送出されます。

   バージョン 3.3 で変更: 以前は "WindowsError" を送出していました。

class ctypes.WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)

   Windows 用: このクラスのインスタンスはロードされた共有ライブラリを
   あらわします。これらのライブラリの関数は "stdcall" 呼び出し規約を使
   用し、デフォルトでは "int" を返すと仮定されます。

   Windows CE では標準呼び出し規約だけが使われます。便宜上、このプラッ
   トフォームでは、 "WinDLL" と "OleDLL" が標準呼び出し規約を使用しま
   す。

これらのライブラリがエクスポートするどの関数でも呼び出す前に Python
GIL (*global interpreter lock*) は解放され、後でまた獲得されます。

class ctypes.PyDLL(name, mode=DEFAULT_MODE, handle=None)

   Python GIL が関数呼び出しの間解放 *されず* 、関数実行の後に Python
   エラーフラグがチェックされるということを除けば、このクラスのインス
   タンスは "CDLL" インスタンスのように振る舞います。エラーフラグがセ
   ットされた場合、 Python 例外が送出されます。

   要するに、これは Python C api 関数を直接呼び出すのに便利だというだ
   けです。

これらすべてのクラスは少なくとも一つの引数、すなわちロードする共有ライ
ブラリのパスを渡して呼び出すことでインスタンス化されます。すでにロード
済みの共有ライブラリへのハンドルがあるなら、 "handle" 名前付き引数とし
て渡すことができます。土台となっているプラットフォームの "dlopen" また
は "LoadLibrary" 関数がプロセスへライブラリをロードするために使われ、
そのライブラリに対するハンドルを得ます。

*mode* パラメータを使うと、ライブラリがどうやってロードされたかを特定
できます。 詳細は *dlopen(3)* マニュアルページを参考にしてください。
Windows では *mode* は無視されます。 POSIX システムでは RTLD_NOW が常
に追加され、設定変更はできません。

*use_errno* 変数が真に設定されたとき、システムの "errno" エラーナンバ
ーに安全にアクセスする ctypes の仕組みが有効化されます。 "ctypes" はシ
ステムの "errno" 変数のスレッド限定のコピーを管理します。もし、
"use_errno=True" の状態で作られた外部関数を呼び出したなら、関数呼び出
し前の "errno" 変数は ctypes のプライベートコピーと置き換えられ、同じ
ことが関数呼び出しの直後にも発生します。

"ctypes.get_errno()" 関数は ctypes のプライベートコピーの値を返します
。そして、 "ctypes.set_errno()" 関数は ctypes のプライベートコピーを置
き換え、以前の値を返します。

*use_last_error* パラメータは、真に設定されたとき、 "GetLastError()"
と "SetLastError()" Windows API によって管理される Windows エラーコー
ドに対するのと同じ仕組みが有効化されます。 "ctypes.get_last_error()"
と "ctypes.set_last_error()" は Windows エラーコードの ctypes プライベ
ートコピーを変更したり要求したりするのに使われます。

ctypes.RTLD_GLOBAL

   *mode* パラメータとして使うフラグ。このフラグが利用できないプラット
   フォームでは、整数のゼロと定義されています。

ctypes.RTLD_LOCAL

   *mode* パラメータとして使うフラグ。これが利用できないプラットフォー
   ムでは、 *RTLD_GLOBAL* と同様です。

ctypes.DEFAULT_MODE

   共有ライブラリをロードするために使われるデフォルトモード。 OSX 10.3
   では *RTLD_GLOBAL* であり、そうでなければ *RTLD_LOCAL* と同じです。

これらのクラスのインスタンスには公開メソッドはありません。共有ライブラ
リからエクスポートされた関数は、属性として、もしくは添字でアクセスでき
ます。属性を通した関数へのアクセスは結果がキャッシュされ、従って繰り返
しアクセスされると毎回同じオブジェクトを返すことに注意してください。そ
れとは反対に、添字を通したアクセスは毎回新しいオブジェクトを返します:

>>> libc.time == libc.time
True
>>> libc['time'] == libc['time']
False

次に述べる公開属性が利用できます。それらの名前はエクスポートされた関数
名に衝突しないように下線で始まります。:

PyDLL._handle

   ライブラリへのアクセスに用いられるシステムハンドル。

PyDLL._name

   コンストラクタに渡されたライブラリの名前。

共有ライブラリは ("LibraryLoader" クラスのインスタンスである) 前もって
作られたオブジェクトの一つを使うことによってロードすることもできます。
それらの "LoadLibrary()" メソッドを呼び出すか、ローダーインスタンスの
属性としてライブラリを取り出すかのどちらかによりロードします。

class ctypes.LibraryLoader(dlltype)

   共有ライブラリをロードするクラス。 *dlltype* は "CDLL" 、 "PyDLL"
   、 "WinDLL" もしくは "OleDLL" 型の一つであるべきです。

   "__getattr__()" は次のような特別なはたらきをします。ライブラリロー
   ダーインスタンスの属性として共有ライブラリにアクセスするとそれがロ
   ードされるということを可能にします。結果はキャッシュされます。その
   ため、繰り返し属性アクセスを行うといつも同じライブラリが返されます
   。

   LoadLibrary(name)

      共有ライブラリをプロセスへロードし、それを返します。このメソッド
      はライブラリの新しいインスタンスを常に返します。

これらの前もって作られたライブラリローダーを利用することができます。:

ctypes.cdll

   "CDLL" インスタンスを作ります。

ctypes.windll

   Windows 用: "WinDLL" インスタンスを作ります。

ctypes.oledll

   Windows 用: "OleDLL" インスタンスを作ります。

ctypes.pydll

   "PyDLL" インスタンスを作ります。

C Python api に直接アクセスするために、すぐに使用できる Python 共有ラ
イブラリオブジェクトが次のように用意されています。

ctypes.pythonapi

   属性として Python C api 関数を公開する "PyDLL" のインスタンス。これ
   らすべての関数は C "int" を返すと仮定されますが、もちろん常に正しい
   とは限りません。そのため、これらの関数を使うためには正しい
   "restype" 属性を代入しなければなりません。


16.16.2.3. 外部関数
-------------------

前節で説明した通り、外部関数はロードされた共有ライブラリの属性としてア
クセスできます。デフォルトではこの方法で作成された関数オブジェクトはど
んな数の引数でも受け取り、引数としてどんな ctypes データのインスタンス
をも受け取り、そして、ライブラリローダーが指定したデフォルトの結果の値
の型を返します。関数オブジェクトはプライベートクラスのインスタンスです
。:

class ctypes._FuncPtr

   C の呼び出し可能外部関数のためのベースクラス。

   外部関数のインスタンスも C 互換データ型です。それらは C の関数ポイ
   ンタを表しています。

   この振る舞いは外部関数オブジェクトの特別な属性に代入することによっ
   て、カスタマイズすることができます。

   restype

      外部関数の結果の型を指定するために ctypes 型を代入する。何も返さ
      ない関数を表す "void" に対しては "None" を使います。

      ctypes 型ではない呼び出し可能な Python オブジェクトを代入するこ
      とは可能です。このような場合、関数が C "int" を返すと仮定され、
      呼び出し可能オブジェクトはこの整数を引数に呼び出されます。さらに
      処理を行ったり、エラーチェックをしたりできるようにするためです。
      これの使用は推奨されません。より柔軟な後処理やエラーチェックのた
      めには "restype" として ctypes 型を使い、 "errcheck" 属性へ呼び
      出し可能オブジェクトを代入してください。

   argtypes

      関数が受け取る引数の型を指定するために ctypes 型のタプルを代入し
      ます。"stdcall" 呼び出し規約を使う関数はこのタプルの長さと同じ数
      の引数で呼び出されます。C 呼び出し規約を使う関数は、追加の不特定
      の引数も取ります。

      外部関数が呼ばれたとき、それぞれの実引数は "argtypes" タプルの要
      素の "from_param()" クラスメソッドへ渡されます。このメソッドは実
      引数を外部関数が受け取るオブジェクトに合わせて変えられるようにし
      ます。例えば、 "argtypes" タプルの "c_char_p" 要素は、 ctypes 変
      換規則にしたがって引数として渡された文字列をバイト列オブジェクト
      へ変換するでしょう。

      新: ctypes 型でない要素を argtypes に入れることができますが、個
      々の要素は引数として使える値 (整数、文字列、 ctypes インスタンス
      ) を返す "from_param()" メソッドを持っていなければなりません。こ
      れにより関数パラメータとしてカスタムオブジェクトを適合するように
      変更できるアダプタが定義可能となります。

   errcheck

      Python 関数または他の呼び出し可能オブジェクトをこの属性に代入し
      ます。呼び出し可能オブジェクトは三つ以上の引数とともに呼び出され
      ます。

      callable(result, func, arguments)

         *result* は外部関数が返すもので、 "restype" 属性で指定されま
         す。

         *func* は外部関数オブジェクト自身で、これにより複数の関数の処
         理結果をチェックまたは後処理するために、同じ呼び出し可能オブ
         ジェクトを再利用できるようになります。

         *arguments* は関数呼び出しに最初に渡されたパラメータが入った
         タプルです。これにより使われた引数に基づいた特別な振る舞いを
         させることができるようになります。

      この関数が返すオブジェクトは外部関数呼び出しから返された値でしょ
      う。しかし、戻り値をチェックして、外部関数呼び出しが失敗している
      なら例外を送出させることもできます。

exception ctypes.ArgumentError

   この例外は外部関数呼び出しが渡された引数を変換できなかったときに送
   出されます。


16.16.2.4. 関数プロトタイプ
---------------------------

外部関数は関数プロトタイプをインスタンス化することによって作成されます
。 関数プロトタイプは C の関数プロトタイプと似ています。実装は定義せず
に、関数 (返り値の型、引数の型、呼び出し規約) を記述します。 ファクト
リ関数は、その関数に要求される返り値の型と引数の型とともに呼び出されま
す。そしてこの関数はデコレータファクトリとしても使え、 "@wrapper" 構文
で他の関数に適用できます。 例については コールバック関数 を参照してく
ださい。

ctypes.CFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)

   返された関数プロトタイプは標準 C 呼び出し規約をつかう関数を作成しま
   す。関数は呼び出されている間 GIL を解放します。 *use_errno* が真に
   設定されれば、呼び出しの前後で System 変数 "errno" の ctypesプライ
   ベートコピーは本当の "errno" の値と交換されます。 *use_last_error*
   も Windows エラーコードに対するのと同様です。

ctypes.WINFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)

   Windows のみ: 返された関数プロトタイプは "stdcall" 呼び出し規約を使
   う関数を作成します。ただし、 "WINFUNCTYPE()" が "CFUNCTYPE()" と同
   じである Windows CE を除きます。関数は呼び出されている間 GIL を解放
   します。 *use_errno* と *use_last_error* は前述と同じ意味を持ちます
   。

ctypes.PYFUNCTYPE(restype, *argtypes)

   返された関数プロトタイプは Python 呼び出し規約を使う関数を作成しま
   す。関数は呼び出されている間 GIL を解放 *しません*。

ファクトリ関数によって作られた関数プロトタイプは呼び出しのパラメータの
型と数に依存した別の方法でインスタンス化することができます。 :

   prototype(address)

      指定されたアドレス(整数でなくてはなりません)の外部関数を返します
      。

   prototype(callable)

      Python の *callable* から C の呼び出し可能関数(コールバック関数)
      を作成します。

   prototype(func_spec[, paramflags])

      共有ライブラリがエクスポートしている外部関数を返します。
      *func_spec* は 2 要素タプル "(name_or_ordinal, library)" でなけ
      ればなりません。第一要素はエクスポートされた関数の名前である文字
      列、またはエクスポートされた関数の序数である小さい整数です。第二
      要素は共有ライブラリインスタンスです。

   prototype(vtbl_index, name[, paramflags[, iid]])

      COM メソッドを呼び出す外部関数を返します。 *vtbl_index* は仮想関
      数テーブルのインデックスで、非負の小さい整数です。 *name* は COM
      メソッドの名前です。 *iid* はオプションのインターフェイス識別子
      へのポインタで、拡張されたエラー情報の提供のために使われます。

      COM メソッドは特殊な呼び出し規約を用います。このメソッドは
      "argtypes" タプルに指定されたパラメータに加えて、第一引数として
      COM インターフェイスへのポインタを必要とします。

   オプションの *paramflags* パラメータは上述した機能より多機能な外部
   関数ラッパーを作成します。

   *paramflags* は "argtypes" と同じ長さのタプルでなければなりません。

   このタプルの個々の要素はパラメータについてのより詳細な情報を持ち、
   1 、 2 もしくは 3 要素を含むタプルでなければなりません。

   第一要素はパラメータについてのフラグの組み合わせを含んだ整数です。

      1
         入力パラメータを関数に指定します。

      2
         出力パラメータ。外部関数が値を書き込みます。

      4
         デフォルトで整数ゼロになる入力パラメータ。

   オプションの第二要素はパラメータ名の文字列です。これが指定された場
   合は、外部関数を名前付きパラメータで呼び出すことができます。

   オプションの第三要素はこのパラメータのデフォルト値です。

この例では、デフォルトパラメータと名前付き引数をサポートするために
Windows の "MessageBoxW" 関数をラップする方法を示します。 windows のヘ
ッダファイルの C の宣言は次の通りです:

   WINUSERAPI int WINAPI
   MessageBoxW(
       HWND hWnd,
       LPCWSTR lpText,
       LPCWSTR lpCaption,
       UINT uType);

"ctypes" を使ってラップします。:

   >>> from ctypes import c_int, WINFUNCTYPE, windll
   >>> from ctypes.wintypes import HWND, LPCWSTR, UINT
   >>> prototype = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT)
   >>> paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", "Hello from ctypes"), (1, "flags", 0)
   >>> MessageBox = prototype(("MessageBoxW", windll.user32), paramflags)

これで外部関数の "MessageBox" を次のような方法で呼び出すことができるよ
うになりました:

   >>> MessageBox()
   >>> MessageBox(text="Spam, spam, spam")
   >>> MessageBox(flags=2, text="foo bar")

二番目の例は出力パラメータについて説明します。 win32 の
"GetWindowRect" 関数は、指定されたウィンドウの大きさを呼び出し側が与え
る "RECT" 構造体へコピーすることで取り出します。 C の宣言はこうです。:

   WINUSERAPI BOOL WINAPI
   GetWindowRect(
        HWND hWnd,
        LPRECT lpRect);

"ctypes" を使ってラップします。:

   >>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError
   >>> from ctypes.wintypes import BOOL, HWND, RECT
   >>> prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT))
   >>> paramflags = (1, "hwnd"), (2, "lprect")
   >>> GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags)
   >>>

出力パラメータを持つ関数は、単一のパラメータがある場合にはその出力パラ
メータ値を、複数のパラメータがある場合には出力パラメータ値が入ったタプ
ルを、それぞれ自動的に返します。そのため、GetWindowRect 関数は呼び出さ
れると RECT インスタンスを返します。

さらに出力処理やエラーチェックを行うために、出力パラメータを
"errcheck" プロトコルと組み合わせることができます。 win32
"GetWindowRect" api 関数は成功したか失敗したかを知らせるために "BOOL"
を返します。そのため、この関数はエラーチェックを行って、 api 呼び出し
が失敗した場合に例外を送出させることができます。:

   >>> def errcheck(result, func, args):
   ...     if not result:
   ...         raise WinError()
   ...     return args
   ...
   >>> GetWindowRect.errcheck = errcheck
   >>>

"errcheck" 関数が受け取った引数タプルを変更なしに返した場合、 "ctypes"
は出力パラメータに対する通常の処理を続けます。 "RECT" インスタンスの代
わりに window 座標のタプルを返すには、関数のフィールドを取り出し、代わ
りにそれらを返すことができます。この場合、通常処理は行われなくなります
:

   >>> def errcheck(result, func, args):
   ...     if not result:
   ...         raise WinError()
   ...     rc = args[1]
   ...     return rc.left, rc.top, rc.bottom, rc.right
   ...
   >>> GetWindowRect.errcheck = errcheck
   >>>


16.16.2.5. ユーティリティー関数
-------------------------------

ctypes.addressof(obj)

   メモリバッファのアドレスを示す整数を返します。 *obj* は ctypes 型の
   インスタンスでなければなりません。

ctypes.alignment(obj_or_type)

   ctypes 型のアライメントの必要条件を返します。 *obj_or_type* は
   ctypes 型またはインスタンスでなければなりません。

ctypes.byref(obj[, offset])

   *obj* (ctypes 型のインスタンスでなければならない) への軽量ポインタ
   を返します。 *offset* はデフォルトでは 0 で、内部ポインターへ加算さ
   れる整数です。

   "byref(obj, offset)" は、 C コードとしては、以下のようにみなされま
   す。:

      (((char *)&obj) + offset)

   返されるオブジェクトは外部関数呼び出しのパラメータとしてのみ使用で
   きます。"pointer(obj)" と似たふるまいをしますが、作成が非常に速く行
   えます。

ctypes.cast(obj, type)

   この関数は C のキャスト演算子に似ています。*obj* と同じメモリブロッ
   クを指している *type* の新しいインスタンスを返します。*type* はポイ
   ンタ型でなければならず、*obj* はポインタとして解釈できるオブジェク
   トでなければなりません。

ctypes.create_string_buffer(init_or_size, size=None)

   この関数は変更可能な文字バッファを作成します。返されるオブジェクト
   は "c_char" の ctypes 配列です。

   *init_or_size* は配列のサイズを指定する整数もしくは配列要素を初期化
   するために使われるバイト列オブジェクトである必要があります。

   バイト列オブジェクトが第一引数として指定されていた場合、配列の最後
   の要素が NUL 終端文字となるように、バイト列オブジェクトの長さより 1
   つ長いバッファを作成します。バイト列の長さを使うべきではない場合は
   、第二引数として整数を渡して、配列の長さを指定することができます。

ctypes.create_unicode_buffer(init_or_size, size=None)

   この関数は変更可能な Unicode 文字バッファを作成します。返されるオブ
   ジェクトは "c_wchar" の ctypes 配列です。

   *init_or_size* は配列のサイズを指定する整数もしくは配列要素を初期化
   するために使われる文字列である必要があります。

   第一引数として文字列が指定された場合は、バッファが文字列の長さより
   一要素分大きく作られます。配列の最後の要素が NUL 終端文字であるため
   です。文字列の長さを使うべきでない場合は、配列のサイズを指定するた
   めに整数を第二引数として渡すことができます。

ctypes.DllCanUnloadNow()

   Windows 用: この関数は ctypes をつかってインプロセス COM サーバーを
   実装できるようにするためのフックです。_ctypes 拡張 dll がエクスポー
   トしている DllCanUnloadNow 関数から呼び出されます。

ctypes.DllGetClassObject()

   Windows 用: この関数は ctypes をつかってインプロセス COM サーバーを
   実装できるようにするためのフックです。"_ctypes" 拡張 dll がエクスポ
   ートしている DllGetClassObject 関数から呼び出されます。

ctypes.util.find_library(name)

   ライブラリを検索し、パス名を返します。 *name* は "lib" のような接頭
   辞、 ".so" や ".dylib" のような接尾辞、そして、バージョンナンバーを
   除くライブラリ名です (これは posix のリンカーオプション "-l" で使わ
   れる書式です) 。もしライブラリが見つからなければ、 "None" を返しま
   す。

   厳密な機能はシステムに依存します。

ctypes.util.find_msvcrt()

   Windows 用: Python と拡張モジュールで使われる VC ランタイムライブラ
   リのファイル名を返します。もしライブラリ名が同定できなければ、
   "None" を返します。

   もし、例えば拡張モジュールにより割り付けられたメモリを "free(void
   *)" で解放する必要があるなら、メモリ割り付けを行ったのと同じライブ
   ラリの関数を使うことが重要です。

ctypes.FormatError([code])

   Windows 用: エラーコード *code* の説明文を返します。エラーコードが
   指定されない場合は、 Windows api 関数 GetLastError を呼び出して、も
   っとも新しいエラーコードが使われます。

ctypes.GetLastError()

   Windows 用: 呼び出し側のスレッド内で Windows によって設定された最新
   のエラーコードを返します。この関数は Windows の *GetLastError()* 関
   数を直接実行します。 ctypes のプライベートなエラーコードのコピーを
   返したりはしません。

ctypes.get_errno()

   システムの "errno" 変数の、スレッドローカルなプライベートコピーを返
   します。

ctypes.get_last_error()

   Windows 用: システムの "LastError" 変数の、スレッドローカルなプライ
   ベートコピーを返します。

ctypes.memmove(dst, src, count)

   標準 C の memmove ライブラリ関数と同じものです。: *count* バイトを
   *src* から *dst* へコピーします。 *dst* と *src* はポインタへ変換可
   能な整数または ctypes インスタンスでなければなりません。

ctypes.memset(dst, c, count)

   標準 C の memset ライブラリ関数と同じものです。: アドレス *dst* の
   メモリブロックを値 *c* を *count* バイト分書き込みます。 *dst* はア
   ドレスを指定する整数または ctypes インスタンスである必要があります
   。

ctypes.POINTER(type)

   このファクトリ関数は新しい ctypes ポインタ型を作成して返します。ポ
   インタ型はキャッシュされ、内部で再利用されます。したがって、この関
   数を繰り返し呼び出してもコストは小さいです。*type* は ctypes 型でな
   ければなりません。

ctypes.pointer(obj)

   この関数は *obj* を指す新しいポインタインスタンスを作成します。戻り
   値は "POINTER(type(obj))" 型のオブジェクトです。

   注意: 外部関数呼び出しへオブジェクトへのポインタを渡したいだけなら
   、はるかに高速な "byref(obj)" を使うべきです。

ctypes.resize(obj, size)

   この関数は *obj* の内部メモリバッファのサイズを変更します。 *obj*
   は ctypes 型のインスタンスでなければなりません。バッファを
   "sizeof(type(obj))" で与えられるオブジェクト型の本来のサイズより小
   さくすることはできませんが、バッファを拡大することはできます。

ctypes.set_errno(value)

   システム変数 "errno" の、呼び出し元スレッドでの ctypes のプライベー
   トコピーの現在値を *value* に設定し、前の値を返します。

ctypes.set_last_error(value)

   Windows 用: システム変数 "LastError" の、呼び出し元スレッドでの
   ctypes のプライベートコピーの現在値を *value* に設定し、前の値を返
   します。

ctypes.sizeof(obj_or_type)

   ctypes の型やインスタンスのメモリバッファのサイズをバイト数で返しま
   す。C の "sizeof" 演算子と同様の動きをします。

ctypes.string_at(address, size=-1)

   この関数はメモリアドレス *address* から始まる C 文字列を返します。
   size が指定された場合はサイズとして使われます。指定されなければ、文
   字列がゼロ終端されていると仮定します。

ctypes.WinError(code=None, descr=None)

   Windows 用: この関数はおそらく ctypes の中で最悪の名前でしょう。こ
   れは OSError のインスタンスを作成します。 *code* が指定されていなか
   った場合、エラーコードを判別するために "GetLastError" が呼び出され
   ます。 *descr* が指定されていなかった場合、エラーの説明文を得るため
   に "FormatError()" が呼び出されます。

   バージョン 3.3 で変更: 以前は "WindowsError" インスタンスが作成され
   ていました。

ctypes.wstring_at(address, size=-1)

   この関数は文字列としてメモリアドレス *address* から始まるワイドキャ
   ラクタ文字列を返します。*size* が指定されたならば、文字列の文字数と
   して使われます。指定されなければ、文字列がゼロ終端されていると仮定
   します。


16.16.2.6. データ型
-------------------

class ctypes._CData

   この非公開クラスはすべての ctypes データ型の共通のベースクラスです
   。他のことはさておき、すべての ctypes 型インスタンスは C 互換データ
   を保持するメモリブロックを内部に持ちます。このメモリブロックのアド
   レスは "addressof()" ヘルパー関数が返します。別のインスタンス変数が
   "_objects" として公開されます。これはメモリブロックがポインタを含む
   場合に存続し続ける必要のある他の Python オブジェクトを含んでいます
   。

   ctypes データ型の共通メソッド、すべてのクラスメソッドが存在します (
   正確には、 *メタクラス* のメソッドです):

   from_buffer(source[, offset])

      このメソッドは *source* オブジェクトのバッファを共有する ctypes
      のインスタンスを返します。 *source* オブジェクトは書き込み可能バ
      ッファインターフェースをサポートしている必要があります。オプショ
      ンの *offset* 引数では *source* バッファのオフセットをバイト単位
      で指定します。デフォルトではゼロです。もし *source* バッファが十
      分に大きくなければ、 "ValueError" が送出されます。

   from_buffer_copy(source[, offset])

      このメソッドは *source* オブジェクトの読み出し可能バッファをコピ
      ーすることで、ctypes のインスタンスを生成します。オプションの
      *offset* 引数では *source* バッファのオフセットをバイト単位で指
      定します。デフォルトではゼロです。もし *source* バッファが十分に
      大きくなければ、 "ValueError" が送出されます。

   from_address(address)

      このメソッドは *address* で指定されたメモリを使って ctypes 型の
      インスタンスを返します。 *address* は整数でなければなりません。

   from_param(obj)

      このメソッドは *obj* を ctypes 型に適合させます。外部関数の
      "argtypes" タプルに、その型があるとき、外部関数呼び出しで実際に
      使われるオブジェクトと共に呼び出されます。

      すべての ctypes のデータ型は、それが型のインスタンスであれば、
      *obj* を返すこのクラスメソッドのデフォルトの実装を持ちます。いく
      つかの型は、別のオブジェクトも受け付けます。

   in_dll(library, name)

      このメソッドは、共有ライブラリによってエクスポートされた ctypes
      型のインスタンスを返します。 *name* はエクスポートされたデータの
      名前で、 *library* はロードされた共有ライブラリです。

   ctypes データ型共通のインスタンス変数:

   _b_base_

      ctypes 型データのインスタンスは、それ自身のメモリブロックを持た
      ず、基底オブジェクトのメモリブロックの一部を共有することがありま
      す。 "_b_base_" 読み出し専用属性は、メモリブロックを保持する
      ctypes の基底オブジェクトです。

   _b_needsfree_

      この読み出し専用の変数は、 ctypes データインスタンスが、それ自身
      に割り当てられたメモリブロックを持つとき true になります。それ以
      外の場合は false になります。

   _objects

      このメンバは "None" 、または、メモリブロックの内容が正しく保つた
      めに、生存させておかなくてはならない Python オブジェクトを持つデ
      ィクショナリです。このオブジェクトはデバッグでのみ使われます。決
      してディクショナリの内容を変更しないで下さい。


16.16.2.7. 基本データ型
-----------------------

class ctypes._SimpleCData

   この非公開クラスは、全ての基本的な ctypes データ型の基底クラスです
   。これは基本的な ctypes データ型に共通の属性を持っているので、ここ
   で触れておきます。 "_SimpleCData" は "_CData" の子クラスなので、そ
   のメソッドと属性を継承しています。ポインタでないかポインタを含まな
   い ctypes データ型は、現在は pickle 化できます。

   インスタンスは一つだけ属性を持ちます:

   value

      この属性は、インスタンスの実際の値を持ちます。整数型とポインタ型
      に対しては整数型、文字型に対しては一文字のバイト列オブジェクト、
      文字へのポインタに対しては Python のバイト列オブジェクトもしくは
      文字列となります。

      "value" 属性が ctypes インスタンスより参照されたとき、大抵の場合
      はそれぞれに対し新しいオブジェクトを返します。 "ctypes" はオリジ
      ナルのオブジェクトを返す実装にはなって *おらず* 新しいオブジェク
      トを構築します。同じことが他の ctypes オブジェクトインスタンスに
      対しても言えます。

基本データ型は、外部関数呼び出しの結果として返されたときや、例えば構造
体のフィールドメンバーや配列要素を取り出すときに、ネイティブの Python
型へ透過的に変換されます。言い換えると、外部関数が "c_char_p" の
"restype" を持つ場合は、 "c_char_p" インスタンスでは *なく* 常に
Python バイト列オブジェクトを受け取ることでしょう。

基本データ型のサブクラスはこの振る舞いを継承 *しません* 。したがって、
外部関数の "restype" が "c_void_p" のサブクラスならば、関数呼び出しか
らこのサブクラスのインスタンスを受け取ります。もちろん、 "value" 属性
にアクセスしてポインタの値を得ることができます。

これらが基本 ctypes データ型です:

class ctypes.c_byte

   C の "signed char" データ型を表し、小整数として値を解釈します。コン
   ストラクタはオプションの整数初期化子を受け取ります。オーバーフロー
   のチェックは行われません。

class ctypes.c_char

   C "char" データ型を表し、単一の文字として値を解釈します。コンストラ
   クタはオプションの文字列初期化子を受け取り、その文字列の長さちょう
   ど一文字である必要があります。

class ctypes.c_char_p

   C "char *" データ型を表し、ゼロ終端文字列へのポインタでなければなり
   ません。バイナリデータを指す可能性のある一般的なポインタに対しては
   "POINTER(c_char)" を使わなければなりません。コンストラクタは整数の
   アドレスもしくはバイト列オブジェクトを受け取ります。

class ctypes.c_double

   C "double" データ型を表します。コンストラクタはオプションの浮動小数
   点数初期化子を受け取ります。

class ctypes.c_longdouble

   C "long double" データ型を表します。コンストラクタはオプションで浮
   動小数点数初期化子を受け取ります。 "sizeof(long double) ==
   sizeof(double)" であるプラットフォームでは "c_double" の別名です。

class ctypes.c_float

   C "float" データ型を表します。コンストラクタはオプションの浮動小数
   点数初期化子を受け取ります。

class ctypes.c_int

   C "signed int" データ型を表します。コンストラクタはオプションの整数
   初期化子を受け取ります。オーバーフローのチェックは行われません。
   "sizeof(int) == sizeof(long)" であるプラットフォームでは、 "c_long"
   の別名です。

class ctypes.c_int8

   C 8-bit "signed int" データ型を表します。たいていは、 "c_byte" の別
   名です。

class ctypes.c_int16

   C 16-bit "signed int" データ型を表します。たいていは、 "c_short" の
   別名です。

class ctypes.c_int32

   C 32-bit "signed int" データ型を表します。たいていは、 "c_int" の別
   名です。

class ctypes.c_int64

   C 64-bit "signed int" データ型を表します。たいていは、 "c_longlong"
   の別名です。

class ctypes.c_long

   C "signed long" データ型を表します。コンストラクタはオプションの整
   数初期化子を受け取ります。オーバーフローのチェックは行われません。

class ctypes.c_longlong

   C "signed long long" データ型を表します。コンストラクタはオプション
   の整数初期化子を受け取ります。オーバーフローのチェックは行われませ
   ん。

class ctypes.c_short

   C "signed short" データ型を表します。コンストラクタはオプションの整
   数初期化子を受け取ります。オーバーフローのチェックは行われません。

class ctypes.c_size_t

   C "size_t" データ型を表します。

class ctypes.c_ssize_t

   C "ssize_t" データ型を表します。

   バージョン 3.2 で追加.

class ctypes.c_ubyte

   C の "unsigned char" データ型を表し、小さな整数として値を解釈します
   。コンストラクタはオプションの整数初期化子を受け取ります; オーバー
   フローのチェックは行われません。

class ctypes.c_uint

   C の  "unsigned int" データ型を表します。コンストラクタはオプション
   の整数初期化子を受け取ります; オーバーフローのチェックは行われませ
   ん。これは、 "sizeof(int) == sizeof(long)" であるプラットフォームで
   は "c_ulong" の別名です。

class ctypes.c_uint8

   C 8-bit "unsigned int" データ型を表します。たいていは、 "c_ubyte"
   の別名です。

class ctypes.c_uint16

   C 16-bit "unsigned int" データ型を表します。たいていは、 "c_ushort"
   の別名です。

class ctypes.c_uint32

   C 32-bit "unsigned int" データ型を表します。たいていは、 "c_uint"
   の別名です。

class ctypes.c_uint64

   C 64-bit "unsigned int" データ型を表します。たいていは、
   "c_ulonglong" の別名です。

class ctypes.c_ulong

   C "unsigned long" データ型を表します。コンストラクタはオプションの
   整数初期化子を受け取ります。オーバーフローのチェックは行われません
   。

class ctypes.c_ulonglong

   C "unsigned long long" データ型を表します。コンストラクタはオプショ
   ンの整数初期化子を受け取ります。オーバーフローのチェックは行われま
   せん。

class ctypes.c_ushort

   C "unsigned short" データ型を表します。コンストラクタはオプションの
   整数初期化子を受け取ります。オーバーフローのチェックは行われません
   。

class ctypes.c_void_p

   C "void *" データ型を表します。値は整数として表されます。コンストラ
   クタはオプションの整数初期化子を受け取ります。

class ctypes.c_wchar

   C "wchar_t" データ型を表し、値は Unicode 文字列の単一の文字として解
   釈されます。コンストラクタはオプションの文字列初期化子を受け取り、
   その文字列の長さはちょうど一文字である必要があります。

class ctypes.c_wchar_p

   C "wchar_t *" データ型を表し、ゼロ終端ワイド文字列へのポインタでな
   ければなりません。コンストラクタは整数のアドレスもしくは文字列を受
   け取ります。

class ctypes.c_bool

   C の "bool" データ型 (より正確には、 C99 以降の  "_Bool") を表しま
   す。 "True" または "False" の値を持ち、コンストラクタは真偽値と解釈
   できるオブジェクトを受け取ります。

class ctypes.HRESULT

   Windows用: "HRESULT" 値を表し、関数またはメソッド呼び出しに対する成
   功またはエラーの情報を含んでいます。

class ctypes.py_object

   C "PyObject *" データ型を表します。引数なしでこれを呼び出すと
   "NULL" "PyObject *" ポインタを作成します。

"ctypes.wintypes" モジュールは他の Windows 固有のデータ型を提供します
。例えば、 "HWND", "WPARAM", "DWORD" です。 "MSG" や "RECT" のような有
用な構造体も定義されています。


16.16.2.8. 構造化データ型
-------------------------

class ctypes.Union(*args, **kw)

   ネイティブのバイトオーダーでの共用体のための抽象ベースクラス。

class ctypes.BigEndianStructure(*args, **kw)

   *ビックエンディアン* バイトオーダーでの構造体のための抽象ベースクラ
   ス。

class ctypes.LittleEndianStructure(*args, **kw)

   *リトルエンディアン* バイトオーダーでの構造体のための抽象ベースクラ
   ス。

ネイティブではないバイトオーダーを持つ構造体にポインタ型フィールドある
いはポインタ型フィールドを含む他のどんなデータ型をも入れることはできま
せん。

class ctypes.Structure(*args, **kw)

   *ネイティブ* のバイトオーダーでの構造体のための抽象ベースクラス。

   具象構造体型と具象共用体型はこれらの型の一つをサブクラス化すること
   で作らなければなりません。少なくとも、 "_fields_" クラス変数を定義
   する必要があります。 "ctypes" は、属性に直接アクセスしてフィールド
   を読み書きできるようにする記述子 (*descriptor*) を作成するでしょう
   。これらは、

   _fields_

      構造体のフィールドを定義するシーケンス。要素は2要素タプルか3要素
      タプルでなければなりません。第一要素はフィールドの名前です。第二
      要素はフィールドの型を指定します。それはどんな ctypes データ型で
      も構いません。

      "c_int" のような整数型のために、オプションの第三要素を与えること
      ができます。フィールドのビット幅を定義する正の小整数である必要が
      あります。

      一つの構造体と共用体の中で、フィールド名はただ一つである必要があ
      ります。これはチェックされません。名前が繰り返しでてきたときにア
      クセスできるのは一つのフィールドだけです。

      Structure サブクラスを定義するクラス文の *後で* 、 "_fields_" ク
      ラス変数を定義することができます。これにより、次のように自身を直
      接または間接的に参照するデータ型を作成できるようになります:

         class List(Structure):
             pass
         List._fields_ = [("pnext", POINTER(List)),
                          ...
                         ]

      しかし、 "_fields_" クラス変数はその型が最初に使われる (インスタ
      ンスが作成される、それに対して "sizeof()" が呼び出されるなど) よ
      り前に定義されていなければなりません。その後 "_fields_" クラス変
      数へ代入すると AttributeError が送出されます。

      構造体型のサブクラスを定義することができ、もしあるならサブクラス
      内で定義された "_fields_" に加えて、ベースクラスのフィールドも継
      承します。

   _pack_

      インスタンスの構造体フィールドのアライメントを上書きできるように
      するオブションの小整数。 "_pack_" は "_fields_" が代入されたとき
      すでに定義されていなければなりません。そうでなければ、何の効果も
      ありません。

   _anonymous_

      無名 (匿名) フィールドの名前が並べあげられたオプションのシーケン
      ス。 "_fields_" が代入されたとき、 "_anonymous_" がすでに定義さ
      れていなければなりません。そうでなければ、何ら影響はありません。

      この変数に並べあげられたフィールドは構造体型もしくは共用体型フィ
      ールドである必要があります。構造体フィールドまたは共用体フィール
      ドを作る必要なく、入れ子になったフィールドに直接アクセスできるよ
      うにするために、 "ctypes" は構造体型の中に記述子を作成します。

      型の例です (Windows):

         class _U(Union):
             _fields_ = [("lptdesc", POINTER(TYPEDESC)),
                         ("lpadesc", POINTER(ARRAYDESC)),
                         ("hreftype", HREFTYPE)]

         class TYPEDESC(Structure):
             _anonymous_ = ("u",)
             _fields_ = [("u", _U),
                         ("vt", VARTYPE)]

      "TYPEDESC" 構造体はCOMデータ型を表現しており、 "vt" フィールドは
      共用体フィールドのどれが有効であるかを指定します。 "u" フィール
      ドは匿名フィールドとして定義されているため、 TYPEDESC インスタン
      スから取り除かれてそのメンバーへ直接アクセスできます。
      "td.lptdesc" と "td.u.lptdesc" は同等ですが、前者がより高速です
      。なぜなら一時的な共用体インスタンスを作る必要がないためです。:

         td = TYPEDESC()
         td.vt = VT_PTR
         td.lptdesc = POINTER(some_type)
         td.u.lptdesc = POINTER(some_type)

   構造体のサブ-サブクラスを定義することができ、ベースクラスのフィール
   ドを継承します。サブクラス定義に別の "_fields_" 変数がある場合は、
   この中で指定されたフィールドはベースクラスのフィールドへ追加されま
   す。

   構造体と共用体のコンストラクタは位置引数とキーワード引数の両方を受
   け取ります。位置引数は "_fields_" の中に現れたのと同じ順番でメンバ
   ーフィールドを初期化するために使われます。コンストラクタのキーワー
   ド引数は属性代入として解釈され、そのため、同じ名前をもつ "_fields_"
   を初期化するか、 "_fields_" に存在しない名前に対しては新しい属性を
   作ります。


16.16.2.9. 配列とポインタ
-------------------------

class ctypes.Array(*args)

   配列のための抽象基底クラスです。

   具象配列型を作成するための推奨される方法は、任意の "ctypes" データ
   型に正の整数を乗算することです。代わりに、この型のサブクラスを作成
   し、 "_length_" と "_type_" のクラス変数を定義することもできます。
   配列の要素は、標準の添え字とスライスによるアクセスを使用して読み書
   きを行うことができます。スライスの読み込みでは、結果のオブジェクト
   自体は "Array" ではありません。

   _length_

      配列の要素数を指定する正の整数。範囲外の添え字を指定すると、
      "IndexError" が送出されます。"len()" がこの整数を返します。

   _type_

      配列内の各要素の型を指定します。

   配列のサブクラスのコンストラクタは、位置引数を受け付けて、配列を順
   番に初期化するために使用します。

class ctypes._Pointer

   ポインタのためのプライベートな抽象基底クラスです。

   具象ポインタ型は、ポイント先の型を持つ "POINTER()" を呼び出すことで
   、作成できます。これは、 "pointer()" により自動的に行われます。

   ポインタが配列を指す場合、その配列の要素は、標準の添え字とスライス
   によるアクセスを使用して読み書きが行えます。ポインタオブジェクトに
   は、サイズがないため、 "len()" 関数は "TypeError" を送出します。負
   の添え字は、(C と同様に) ポインタの *前* のメモリから読み込み、範囲
   外の添え字はおそらく (幸運な場合でも) アクセス違反によりクラッシュ
   を起こします。

   _type_

      ポイント先の型を指定します。

   contents

      ポインタが指すオブジェクトを返します。この属性に割り当てると、ポ
      インタが割り当てられたオブジェクトを指すようになります。
