###
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 ?
    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
    >>>