在这篇博客中,我们将探讨如何在 Python 中调用 C 函数,以及如何在 C 中调用 Python 函数。利用这两种方法,你可以在项目中充分发挥 Python 的简洁性和 C 的高性能优势。
目录
- [Python 调用 C 函数](#Python 调用 C 函数)
- [使用 ctypes](#使用 ctypes)
- [使用 Cython](#使用 Cython)
- [C 调用 Python 函数](#C 调用 Python 函数)
- [使用 Python C API](#使用 Python C API)
Python 调用 C 函数
使用 ctypes
ctypes
是 Python 的一个外部函数库,允许调用动态链接库(DLL 或共享库)的函数。
例子:简单的 C 函数
首先,我们编写一个简单的 C 函数,并将其编译成共享库。
hello.c
c
#include <stdio.h>
void say_hello(const char* name) {
printf("Hello, %s!\n", name);
}
编译这个 C 文件生成共享库:
bash
gcc -shared -o libhello.so -fPIC hello.c
然后,我们使用 ctypes
在 Python 中调用这个 C 函数。
call_hello.py
python
import ctypes
# 加载共享库
lib = ctypes.CDLL('./libhello.so')
# 定义函数原型
lib.say_hello.argtypes = [ctypes.c_char_p]
lib.say_hello.restype = None
# 调用 C 函数
lib.say_hello(b"World")
使用 Cython
Cython 是一种使得 C 代码可以无缝集成到 Python 的工具。它允许你在 Python 代码中嵌入 C 代码,从而提升性能。
例子:简单的 C 函数
我们编写一个简单的 Cython 文件。
hello.pyx
cython
cdef extern from "hello.h":
void say_hello(const char* name)
def call_hello(name):
say_hello(name.encode('utf-8'))
编写一个 C 头文件。
hello.h
c
void say_hello(const char* name);
编写一个 C 文件。
hello.c
c
#include <stdio.h>
#include "hello.h"
void say_hello(const char* name) {
printf("Hello, %s!\n", name);
}
编写一个 setup 文件来编译 Cython 代码。
python
from setuptools import setup
from setuptools.extension import Extension
from Cython.Build import cythonize
extensions = [
Extension("hello", ["hello.pyx", "hello.c"])
]
setup(
ext_modules=cythonize(extensions)
)
编译 Cython 代码:
bash
python setup.py build_ext --inplace
编写一个 Python 文件调用 Cython 代码。
call_hello.py
python
import hello
hello.call_hello("World")
C 调用 Python 函数
使用 Python C API
Python 提供了一个 C API,使得 C 代码可以嵌入到 Python 中。
例子:调用 Python 函数
首先,我们编写一个简单的 Python 函数。
python
def greet(name):
return f"Hello, {name}!"
然后,我们编写一个 C 文件来调用这个 Python 函数。
call_python.c
c
#include <Python.h>
int main(int argc, char *argv[]) {
// 初始化 Python 解释器
Py_Initialize();
// 添加当前目录到模块搜索路径
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('.')");
// 导入 Python 脚本
PyObject *pName = PyUnicode_DecodeFSDefault("script");
PyObject *pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (pModule != NULL) {
// 获取函数
PyObject *pFunc = PyObject_GetAttrString(pModule, "greet");
if (PyCallable_Check(pFunc)) {
// 创建参数
PyObject *pArgs = PyTuple_Pack(1, PyUnicode_FromString("World"));
// 调用函数
PyObject *pValue = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
if (pValue != NULL) {
printf("Result of call: %s\n", PyUnicode_AsUTF8(pValue));
Py_DECREF(pValue);
} else {
Py_DECREF(pFunc);
Py_DECREF(pModule);
PyErr_Print();
fprintf(stderr, "Call failed\n");
return 1;
}
} else {
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr, "Cannot find function \"greet\"\n");
}
Py_XDECREF(pFunc);
Py_DECREF(pModule);
} else {
PyErr_Print();
fprintf(stderr, "Failed to load \"script\"\n");
return 1;
}
// 结束 Python 解释器
Py_Finalize();
return 0;
}
编译并运行这个 C 文件:
bash
gcc -o call_python call_python.c -I/usr/include/python3.8 -lpython3.8
./call_python
结论
在这篇博客中,我们展示了如何在 Python 中调用 C 函数,以及如何在 C 中调用 Python 函数。通过这两种方法,可以在项目中利用 Python 的简洁性和 C 的高性能优势。希望这篇教程对你有所帮助!