14.14.1.3 関数を呼び出す

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

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

>>> print libc.time(None) # doctest: +SKIP
1150640792
>>> print hex(windll.kernel32.GetModuleHandleA(None)) # doctest: +WINDOWS
0x1d000000
>>>

ctypesは引数の数を間違えたり、あるいは呼び出し規約を間違えた関数呼び出しから あなたを守ろうとします。残念ながら、これはWindowsでしか機能しません。 関数が返った後にスタックを調べることでこれを行います。したがって、 エラーは発生しますが、その関数は呼び出された後です:

>>> windll.kernel32.GetModuleHandleA() # doctest: +WINDOWS
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: Procedure probably called with not enough arguments (4 bytes missing)
>>> windll.kernel32.GetModuleHandleA(0, 0) # doctest: +WINDOWS
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
ValueError: Procedure probably called with too many arguments (4 bytes in excess)
>>>

同じ例外がcdecl呼び出し規約を使ってstdcall関数を呼び出したときに発生しますし、 逆の場合も同様です。

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

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

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

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

>>> windll.kernel32.GetModuleHandleA(32) # doctest: +WINDOWS
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
WindowsError: exception: access violation reading 0x00000020
>>>

しかし、ctypesを使ってPythonをクラッシュさせる方法は十分なほどあるので、 よく注意すべきです。

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

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

ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。