0Pricing
Python Academy · 课时

ctypes:从 Python 调用 C 库

加载共享库,并使用 ctypes 调用 C 函数。

ctypes:从 Python 调用 C 库 是 CoddyKit 上的免费 Python Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 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 接口,请使用 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

传递指针

请使用 ctypes.byref(var) 或 ctypes.pointer(var),将指针传递给 C 变量。

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())

错误处理

请检查 ctypes.get_last_error()(Windows),或者对于以特殊值返回的错误,使用 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

通过 ctypes 直接调用 OpenSSL 的 SHA256,无需任何 Python 绑定库。

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。请使用 Structure 表示 C 结构体,使用 TypeClass * N 表示数组,并使用 CFUNCTYPE 表示回调。

常见问题解答

「ctypes:从 Python 调用 C 库」课时是免费的吗?

是的 — 「ctypes:从 Python 调用 C 库」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Python Academy 课程的其余内容,请升级到 CoddyKit PRO。 Python Academy 课程共包含 4 节课。

「ctypes:从 Python 调用 C 库」这节课中我会学到什么?

加载共享库,并使用 ctypes 调用 C 函数。 你通过在浏览器中直接运行的动手代码来练习 Python Academy,全天候 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