0Pricing
Python Academy · レッスン

ctypes: Python から C ライブラリを呼び出す

ctypes で共有ライブラリを読み込み、C 関数を呼び出します。

「ctypes: Python から C ライブラリを呼び出す」はCoddyKit上の無料Python Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはPython Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Python Academyコースには全4レッスンが含まれています。

ctypesとは

ctypes は、共有Cライブラリを読み込み、その関数をPythonから呼び出すための標準ライブラリモジュールです。コンパイルは必要ありません。

import ctypes

# Load the C standard library
libc = ctypes.CDLL("libc.so.6")   # Linux
# libc = ctypes.CDLL("libSystem.dylib")  # macOS

libc.puts(b"Hello from C!")

ライブラリの読み込み

cdeclの呼び出し規約(ほとんどのCライブラリ)には ctypes.CDLL を使用し、Windowsのstdcall APIには WinDLL を使用します。

import ctypes

# Platform-independent approach:
import ctypes.util
libm_name = ctypes.util.find_library("m")
libm = ctypes.CDLL(libm_name)

result = libm.sqrt
result.restype = ctypes.c_double
result.argtypes = [ctypes.c_double]
print(result(2.0))   # 1.4142...

Cのデータ型

ctypesのクラスを使用して、Pythonの型をCの型に対応付けます。c_int、c_double、c_char_p、c_void_p などがあります。

import ctypes

x = ctypes.c_int(42)
print(x.value)   # 42

d = ctypes.c_double(3.14)
print(d.value)   # 3.14

s = ctypes.c_char_p(b"hello")
print(s.value)   # b"hello"

argtypesとrestypeの設定

型の不一致による予期しないクラッシュを避けるため、必ず argtypes(引数の型)と restype(戻り値の型)を宣言します。

import ctypes, ctypes.util

libm = ctypes.CDLL(ctypes.util.find_library("m"))

libm.pow.argtypes = [ctypes.c_double, ctypes.c_double]
libm.pow.restype  = ctypes.c_double

print(libm.pow(2.0, 10.0))   # 1024.0

ポインターの受け渡し

C変数へのポインターを渡すには、ctypes.byref(var) または ctypes.pointer(var) を使用します。

import ctypes

libc = ctypes.CDLL(None)   # None = current process

value = ctypes.c_int(0)
# Passing pointer to C function:
# libc.some_func(ctypes.byref(value))
print(value.value)

構造体

ctypes.Structure を継承し、_fields_ を列挙してCの構造体を定義します。

import ctypes

class Point(ctypes.Structure):
    _fields_ = [
        ("x", ctypes.c_double),
        ("y", ctypes.c_double),
    ]

p = Point(1.0, 2.0)
print(p.x, p.y)   # 1.0 2.0

配列

TypeClass * N を使用してCの配列を作成します。

import ctypes

IntArray5 = ctypes.c_int * 5
arr = IntArray5(10, 20, 30, 40, 50)
for v in arr:
    print(v, end=" ")   # 10 20 30 40 50

コールバック(関数ポインター)

ctypes.CFUNCTYPE を使用して、コールバックとして渡せるCから呼び出し可能なPython関数を作成します。

import ctypes

CompareFunc = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int)

def my_compare(a, b):
    return a - b

c_compare = CompareFunc(my_compare)
# Pass c_compare to a C function expecting a comparator

Windows DLLの読み込み

Windowsでは、stdcall規約を使用するDLL(Windows APIなど)に ctypes.WinDLL を使用します。

import ctypes   # Windows only

kernel32 = ctypes.WinDLL("kernel32", use_last_error=True)
kernel32.GetTickCount.restype = ctypes.c_ulong
print(kernel32.GetTickCount())

エラー処理

Windowsでは ctypes.get_last_error() を確認し、特殊な値として返されるエラーにはPythonレベルのtry/exceptを使用します。

import ctypes

# Many C functions return -1 or NULL on error:
result = some_c_function()
if result == -1:
    raise OSError("C function failed")

# For errno on POSIX:
import os
if result < 0:
    raise OSError(os.strerror(ctypes.get_errno()))

実践例:OpenSSLによるSHA-256

Pythonのバインディングライブラリを使わずに、ctypes経由でOpenSSLのSHA256を直接呼び出します。

import ctypes, ctypes.util

libcrypto = ctypes.CDLL(ctypes.util.find_library("crypto"))

SHA256 = libcrypto.SHA256
SHA256.argtypes = [ctypes.c_char_p, ctypes.c_size_t, ctypes.c_char_p]
SHA256.restype  = ctypes.c_char_p

buf = ctypes.create_string_buffer(32)
SHA256(b"hello", 5, buf)
print(buf.raw.hex())

確認問題

ctypesの関数に必ず argtypes と restype を設定する必要があるのはなぜですか?

まとめ

ctypesは、コンパイルなしで共有Cライブラリを読み込みます。すべての関数に argtypes と restype を宣言してください。Cの構造体には Structure、配列には TypeClass * N、コールバックには CFUNCTYPE を使用します。

よくある質問

「ctypes: Python から C ライブラリを呼び出す」レッスンは無料ですか?

はい。「ctypes: Python から C ライブラリを呼び出す」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Python Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Python Academyコースには全4レッスンが含まれています。

「ctypes: Python から C ライブラリを呼び出す」で何を学びますか?

ctypes で共有ライブラリを読み込み、C 関数を呼び出します。 ブラウザで直接実行するハンズオンコードでPython Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Python Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのPython Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「ctypes: Python から C ライブラリを呼び出す」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このPython Academyレッスンでコードを書いて実行できますか?

はい。すべてのPython Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. C 拡張の理由: 用途とトレードオフ
  2. ctypes: Python から C ライブラリを呼び出す
  3. cffi: C 外部関数インターフェース
  4. Python C 拡張モジュールの作成
← Python Academyに戻る