• Python3:与C/C++语言的混合编程


    python3与C/C++语言混合编程,是一个常用的协作方式,可以结合Python3的方便及强大的库与C/C++的高效与快捷。

    混合编程时C语言文件需要提供以下几部分的支持:

    1. 包含Python.h,对此需要通过:sudo apt-get install python3-dev 进行安装
    2. C语言的功能实现函数
    3. Python的模块接口
    4. Python的接口映射函数
    5. Python模块的初始化函数
    1. //func.c
    2. #include //包含Python.h头文件,以引入python的数据结构
    3. #include
    4. #define NULL 0
    5. //C语言的功能实现函数
    6. static int do_add(int a, int b)
    7. {
    8. int sum = a + b;
    9. printf("c call do_add, %d + %d = %d\n", a, b, sum);
    10. return sum;
    11. }
    12. //Python的模块接口函数
    13. static PyObject* add(PyObject *self, PyObject *args)
    14. {
    15. int a = 0, b = 0;
    16. if(!PyArg_ParseTuple(args, "ii", &a, &b)) //通过PyArg_ParseTuple获得Python模块调用时,传递的函数参数
    17. {
    18. return NULL;
    19. }
    20. int result = do_add(a, b); //调用C语言功能实现函数,完成具体的功能
    21. return Py_BuildValue("i", result); //构建PyObject对象作为返回值
    22. }
    23. //Python接口映射函数
    24. /* 关于参数{ "add", (PyCFunction)add, METH_VARARGS, "add" }的说明
    25. 第一个参数:为此模块对外提供的接口函数的名字
    26. 第二个参数:为接口函数的函数指针
    27. 第三个参数:一般是METH_VARARGS;
    28. 如果想传入关键字参数,可以与MET_KEYWORDS进行或运算;
    29. 如果不接受任何参数,可以给其赋值为METH_NOARGS
    30. 第四个参数:函数的文档字符串,可以直接给其赋值为NULL
    31. */
    32. static PyMethodDef func_methods[] = {
    33. { "add", (PyCFunction)add, METH_VARARGS, "add" },
    34. { NULL, NULL, 0, NULL }
    35. };
    36. //Python初始化模块所需的数据结构
    37. static struct PyModuleDef func_module = {
    38. PyModuleDef_HEAD_INIT,
    39. "func", /* 模块名*/
    40. NULL, /* 模块文档字符串,通常为NULL */
    41. -1, /* 模块每个解释器状态的大小,如果模块将状态保存在全局变量中,则为-1 */
    42. func_methods /* 模块所提供的接口映射函数列表 */
    43. };
    44. //Python模块的初始化函数
    45. PyMODINIT_FUNC PyInit_func(void) //该函数的名称为PyInit_模块名
    46. {
    47. return PyModule_Create(&func_module); //使用数据结构func_module进行初始化
    48. }

     除了C语言文件外,还需要一个setup.py文件,用于在编译C语文件时使用

    1. #setup.py
    2. #通过:sudo apt-get install python3-distutils,可以安装distutils
    3. from distutils.core import setup, Extension
    4. #name='c_func',用于包名
    5. #ext_modules,用于指出包内包含的模块列表
    6. #Extension,用于描述模块名及其对应的C语言文件,还可以通过include_dirs=['aa', 'bb']设置头文件目录,libraries=['cc', 'dd']依赖库的列表
    7. setup(name='c_func', ext_modules=[Extension('func', sources=['func.c'])])

     完成了C语言文件和setup.py后可以通过如下命令进行编译:

    1. python3 setup.py build
    2. python3 setup.py install
    3. python3 setup.py build_ext --inplace

    编译后,当前目录下会参数一个so文件,比如:

    func.cpython-38-x86_64-linux-gnu.so

    其中cpython-38-x86_64-linux-gnu为平台的名,可以不用关注

    此时,可以被Python使用的C语言模块已经准备好,可以通过如果程序进行使用:

    1. #fun.py
    2. import func #导入模块
    3. if __name__ == '__main__':
    4. result = func.add(1, 9) #调用模块的接口函数add
    5. print(result)

    python3 ./fun.py  #运行程序输出:
    c call do_add, 1 + 9 = 10
    10

    可见Python程序成功的调用了C语言程序,实现了混合编程

  • 相关阅读:
    《JavaSE-第十七章》之LinkedList
    vue的子组件
    组合数(1) 用Vector实现获取所有组合数列表的QT实现
    Ribbon学习笔记一
    驱动开发day8
    18.webpack4之HMR
    Go高性能之方法接收器 - 指针vs值
    微服务架构必备技术栈:万变不离其宗的奥义!
    Flutter 匠心千刃 | SHA256 加密
    代码随想录动态规划——不同路径
  • 原文地址:https://blog.csdn.net/jiemashizhen/article/details/126312567