You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Python代码与C代码之间的互通调用

Python与C代码互通调用方案

场景1:Python调用C侧定义的函数

以下是3种常用实现方式,按上手难度从低到高排序:

  • ctypes方案(最易用,无需修改原有C代码)
    原理是直接加载C编译的动态库,在Python侧做类型映射后直接调用函数。
    1. 编写C代码(以test.c为例):
    // 示例C函数
    int add(int a, int b) {
        return a + b;
    }
    
    1. 编译为动态库:
      • Linux/macOS 执行命令:gcc -shared -fPIC test.c -o libtest.so
      • Windows 执行命令:gcc -shared test.c -o test.dll
    2. Python侧调用代码:
    import ctypes
    # 加载动态库,Windows替换路径为test.dll
    lib = ctypes.CDLL("./libtest.so")
    # 可选:显式指定参数、返回值类型,避免类型不匹配错误
    lib.add.argtypes = [ctypes.c_int, ctypes.c_int]
    lib.add.restype = ctypes.c_int
    # 调用C函数
    res = lib.add(1, 2)
    print(res) # 输出3
    
  • Python C API 方案(性能最高,适合写高性能扩展)
    按照Python官方扩展规范编写C代码,编译后可直接作为Python模块导入使用。
    示例扩展代码:
    #include <Python.h>
    
    static PyObject* add_c(PyObject* self, PyObject* args) {
        int a, b;
        // 解析Python传入的参数
        if (!PyArg_ParseTuple(args, "ii", &a, &b))
            return NULL;
        // 返回Python类型的结果
        return PyLong_FromLong(a + b);
    }
    
    // 方法映射表
    static PyMethodDef TestMethods[] = {
        {"add", add_c, METH_VARARGS, "计算两个整数的和"},
        {NULL, NULL, 0, NULL} // 结束标记
    };
    
    // 模块定义
    static struct PyModuleDef testmodule = {
        PyModuleDef_HEAD_INIT,
        "test", // 模块名
        NULL,
        -1,
        TestMethods
    };
    
    // 模块初始化入口
    PyMODINIT_FUNC PyInit_test(void) {
        return PyModule_Create(&testmodule);
    }
    
    编译为扩展模块后,在Python中直接import test,调用test.add(1,2)即可。
  • Cython方案(兼顾开发效率和性能)
    用类Python的语法编写逻辑,自动转译为C代码并编译为Python扩展,适合需要同时和C、Python代码做复杂交互的场景。

场景2:C代码调用Python侧定义的函数

原理是在C程序中嵌入Python解释器,加载Python模块后调用目标函数。
示例步骤:

  1. 先编写Python模块test_py.py:
def add(a, b):
    return a + b
  1. 编写C调用代码:
#include <Python.h>
#include <stdio.h>

int main() {
    // 初始化Python解释器
    Py_Initialize();
    if (!Py_IsInitialized()) {
        return -1;
    }
    // 将当前目录加入Python模块搜索路径
    PyRun_SimpleString("import sys; sys.path.append('.')");
    // 导入Python模块
    PyObject* p_module = PyImport_ImportModule("test_py");
    if (!p_module) {
        Py_Finalize();
        return -1;
    }
    // 获取目标函数对象
    PyObject* p_func = PyObject_GetAttrString(p_module, "add");
    if (!p_func || !PyCallable_Check(p_func)) {
        Py_XDECREF(p_func);
        Py_XDECREF(p_module);
        Py_Finalize();
        return -1;
    }
    // 构造传入参数
    PyObject* p_args = PyTuple_New(2);
    PyTuple_SetItem(p_args, 0, PyLong_FromLong(1));
    PyTuple_SetItem(p_args, 1, PyLong_FromLong(2));
    // 调用Python函数
    PyObject* p_res = PyObject_CallObject(p_func, p_args);
    int res = PyLong_AsLong(p_res);
    printf("调用结果:%d\n", res); // 输出3
    // 释放所有Python对象引用,避免内存泄漏
    Py_XDECREF(p_res);
    Py_XDECREF(p_args);
    Py_XDECREF(p_func);
    Py_XDECREF(p_module);
    // 关闭Python解释器
    Py_Finalize();
    return 0;
}
  1. 编译C程序(以Linux为例,替换3.x为你的Python版本,比如3.10):
    gcc main.c -o main -I/usr/include/python3.x -lpython3.x

通用注意事项

  • 两种语言交互时必须做显式类型转换,C的基础类型和Python对象不直接兼容
  • 使用Python C API时注意管理引用计数,否则会出现内存泄漏或程序崩溃
  • 编译动态库和二进制程序时要和Python的架构(32位/64位)、版本匹配

内容的提问来源于stack exchange,提问作者EVI FELDI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 15:15:04