在 Python 中调用 C 语言代码是常见的需求,尤其在需要高性能计算、访问底层系统功能或复用已有 C 代码时。Python 提供了多种方式来实现与 C 语言的交互,主要包括以下几种主流方法:
📌 总结对比
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
ctypes |
简单,无需编译 | 类型声明繁琐 | 调用已有 C 动态库 |
| C 扩展 | 性能最佳,完全控制 | 学习成本高 | 高性能模块开发 |
| Cython | 易于编写,性能好 | 需要编译 | 渐进式优化 Python |
subprocess |
简单易用 | 性能差 | 调用外部程序 |
✅ 1. 使用 ctypes 模块(无需编译 Python 扩展)
适用场景:
- 快速调用已有的 C 动态库(如
.dll、.so、.dylib) - 无需编写额外的 Python 扩展模块
步骤:
1. 编写 C 函数并编译为共享库
// example.c #include <stdio.h>int add(int a, int b) {return a + b; }
编译为共享库(Linux/macOS): bash
gcc -shared -fPIC -o libexample.so example.c
(Windows): bash
gcc -shared -o example.dll example.c
2. 在 Python 中调用
import ctypes# 加载共享库(注意路径和后缀) lib = ctypes.CDLL('./libexample.so') # Windows: './example.dll'# 声明参数和返回值类型 lib.add.argtypes = [ctypes.c_int, ctypes.c_int] lib.add.restype = ctypes.c_int# 调用 C 函数 result = lib.add(3, 4) print(result) # 输出 7
优点:
- 简单易用,无需编译 Python 扩展
- 适合调用已有 C 动态库
缺点:
- 类型声明繁琐
- 性能略低于 C 扩展
- 不支持复杂结构体或回调函数
✅ 2. 编写 C 扩展模块(Python C API)
适用场景:
- 需要高性能的 C 代码嵌入 Python
- 构建可导入的 Python 模块
步骤:
1. 编写 C 扩展代码
// examplemodule.c #include <Python.h>static PyObject* example_add(PyObject* self, PyObject* args) {int a, b;if (!PyArg_ParseTuple(args, "ii", &a, &b)) {return NULL;}return Py_BuildValue("i", a + b); }static PyMethodDef ExampleMethods[] = {{"add", example_add, METH_VARARGS, "Add two integers"},{NULL, NULL, 0, NULL} };static struct PyModuleDef examplemodule = {PyModuleDef_HEAD_INIT,"example",NULL,-1,ExampleMethods };PyMODINIT_FUNC PyInit_example(void) {return PyModule_Create(&examplemodule); }
2. 编写 setup.py 编译模块
# setup.py from setuptools import setup, Extensionmodule = Extension('example', sources=['examplemodule.c'])setup(name='example',version='1.0',description='Example C Extension',ext_modules=[module] )
3. 安装并使用模块
python setup.py build_ext --inplace
python
import example print(example.add(3, 4)) # 输出 7
优点:
- 性能最佳
- 可以完全控制 C 与 Python 的交互
- 可以与 Python 对象交互(如列表、字典)
缺点:
- 编写复杂,需要熟悉 Python C API
- 容易出错(如引用计数、类型检查)
- //-TODO 需要编译
✅ 3. 使用 Cython(Python 与 C 的混合编程)
适用场景:
- 需要将 Python 代码编译为 C 代码以提升性能
- 渐进式优化 Python 代码
步骤:
1. 编写 .pyx 文件
# example.pyx def add(int a, int b):return a + b
2. 编写 setup.py 编译为 C 扩展
# setup.py from setuptools import setup from Cython.Build import cythonizesetup(ext_modules=cythonize("example.pyx") )
3. 编译并使用
python setup.py build_ext --inplace
import example print(example.add(3, 4)) # 输出 7
优点:
- 语法接近 Python,学习曲线低
- 支持类型注解,可生成高性能 C 代码
- 可以直接调用 C 函数和结构体
缺点:
- 仍需编译过程
- 对复杂 C 接口支持不如纯 C 扩展
✅ 4. 使用 subprocess 调用外部 C 程序(非函数级)
适用场景:
- 调用独立的 C 程序(如命令行工具)
- 无需函数级集成
import subprocessresult = subprocess.run(['./my_c_program', '3', '4'], capture_output=True, text=True) print(result.stdout)
优点:
- 简单,适合脚本调用
缺点:
- 性能差
- 无法直接传递复杂数据结构
- 不适合频繁调用
🚨 常见问题与注意事项
- 类型声明不匹配:如
ctypes中未正确设置argtypes和restype,可能导致崩溃。 - 引用计数管理:在 C 扩展中,忘记
Py_INCREF或Py_DECREF可能导致内存泄漏或崩溃。 - 编译环境依赖:C 扩展和 Cython 需要安装 C 编译器(如 GCC 或 MSVC)。
- 跨平台兼容性:不同系统下共享库的后缀不同(
.so/.dll/.dylib),需注意路径问题。
✅ 推荐选择
- 快速调用已有 C 库 → 使用
ctypes - 高性能 C 扩展模块 → 使用 Python C API
- 渐进式性能优化 → 使用 Cython
- 调用外部 C 程序 → 使用
subprocess
根据你的具体需求选择合适的方法即可。