在Linux环境底下 用C语言执行Python程序

在Linux环境底下 用C语言执行Python程序

文章目录

  • 在Linux环境底下 用C语言执行Python程序
    • 1、环境安装&检测
    • 2、C语言调用Python语句
      • 2.1 直接调用python语句
      • 2.2 调用无参python函数
      • 2.3 调用有参python函数

1、环境安装&检测

  • 通过C语言调用Python代码,需要先安装libpython3的 dev依赖库(不同的ubuntu版本下,python版本 可能会有差异, 比如ubuntu 22.04里是libpython3.10-dev)。

  • 首先可以通过以下命令验证是否是否已经存在python3的dev包

  • dpkg -l | grep libpython3

    –>正常会有类似如下的输出,出现"libpython3"和 “dev”,如libpython3.10-dev即可:

    pg@pg-Default-string:~$ dpkg -l | grep libpythonii libpython3-dev:amd64 3.10.6-1~22.04
    amd64 header files and a static library for Python (default)
    ii libpython3-stdlib:amd64 3.10.6-1~22.04 amd64 interactive high-level object-oriented language (default python3 version)
    ii libpython3.10:amd64 3.10.12-1~22.04.2 amd64 Shared Python runtime library (version 3.10)
    ii libpython3.10-dev:amd64 3.10.12-1~22.04.2 amd64 Header files and a static library for Python (v3.10)
    ii libpython3.10-minimal:amd64 3.10.12-1~22.04.2 amd64 Minimal subset of the Python language (version 3.10)
    ii libpython3.10-stdlib:amd64 3.10.12-1~22.04.2 amd64 Interactive high-level object-oriented language (standardlibrary, version 3.10)
    

    –> 如果没有, 可以通过apt命令安装相关的dev包:

    sudo apt install libpython3.10-dev
    Orangepi Zero2 //全志H616开发学习文档 
    

2、C语言调用Python语句

2.1 直接调用python语句

  • 我们先来一个简单的例子
// simpledemo.c
#include "Python.h"
int main()
{Py_Initialize(); // 初始化//int PyRun_SimpleString(const char *command)PyRun_SimpleString("print ('funny')");Py_Finalize(); //释放资源; 最后在程序结束时使用Py_Finalize()函数关闭Python解释器,并释放资源
}

然要编译和运行这个程序,可以使用以下命令(假设使用的是gcc编译器和Python 3.10版本):

gcc simpledemo.c -o simpledemo -I /usr/include/python3.10 -l python3.10 ./simpledemo

–>正常输出

funny

2.2 调用无参python函数

  • 上文调用了print (‘funny’)这条语句,现在把这条语句放到 nopara.py的文件的函数里, 如下
#nopara.py文件
def say_funny():print('funny')

接下来用C语言进行调用,注意文件后缀。

//nopara.c
#if 0
1、包含Python.h头文件,以便使用Python API。
2、使用void Py_Initialize()初始化Python解释器,
3、使用PyObject *PyImport_ImportModule(const char *name)和PyObject
*PyObject_GetAttrString(PyObject *o, const char *attr_name)获取sys.path对象,并利用
int PyList_Append(PyObject *list, PyObject *item)将当前路径.添加到sys.path中,以便加载
当前的Python模块(Python文件即python模块)4、使用PyObject *PyImport_ImportModule(const char *name)函数导入Python模块,并检查是否
有错误。
5、使用PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)函数获取
Python函数对象,并检查是否可调用。
6、使用PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用
Python函数,并获取返回值。
7、使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象。
8、结束时调用void Py_Finalize()函数关闭Python解释器。
相关的函数参数说明参考网站(网站左上角输入函数名即可开始搜索):
https://docs.python.org/zh-cn/3/c-api/import.html
#endif#include <Python.h>
int main()
{Py_Initialize();//创建新的python环境,加载所有内置模块和扩展模块,-->c中执行py// 将当前路径添加到sys.path中PyObject *sys = PyImport_ImportModule("sys");PyObject *path = PyObject_GetAttrString(sys, "path");//获取引用PyList_Append(path, PyUnicode_FromString("."));//将当前路径.添加到sys.path中,以便加载当前的Python模块(Python文件即python模块)。// 导入nopara模块PyObject *pModule = PyImport_ImportModule("nopara");if (!pModule){PyErr_Print();printf("ERROR: failed to load nopara.py\n");return 1;}// 获取say_funny函数对象PyObject *pFunc = PyObject_GetAttrString(pModule, "say_funny");if (!pFunc || !PyCallable_Check(pFunc)){PyErr_Print();printf("ERROR: function say_funny not found or not callable\n");return 1;}// 调用say_funny函数并获取返回值PyObject *pValue = PyObject_CallObject(pFunc, NULL);if (!pValue){PyErr_Print();printf("ERROR: function call failed\n");return 1;}// 释放所有引用的Python对象Py_DECREF(pValue);Py_DECREF(pFunc);Py_DECREF(pModule);// 关闭Python解释器Py_Finalize();return 0;
}

要编译和运行这个程序,可以使用以下命令(假设使用的是gcc编译器和Python 3.10版本)

gcc -o nopara nopara.c -I /usr/include/python3.10/ -l python3.10 ./nopara

–>正常输出

funny

2.3 调用有参python函数

  • C语言调用python有参函数,首先定义一个带参数和返回值的函数
#nopara.py文件
import sysdef say_funny(s):print('funny')return s
# print(sys.path)

接下来用C语言进行调用,调用的流程无参函数的调用方式几乎是一样的是的:

//nopara.c
#if 0
1、包含Python.h头文件,以便使用Python API。
2、使用void Py_Initialize()初始化Python解释器,
3、使用PyObject *PyImport_ImportModule(const char *name)和PyObject
*PyObject_GetAttrString(PyObject *o, const char *attr_name)获取sys.path对象,并利用
int PyList_Append(PyObject *list, PyObject *item)将当前路径.添加到sys.path中,以便加载
当前的Python模块(Python文件即python模块)4、使用PyObject *PyImport_ImportModule(const char *name)函数导入Python模块,并检查是否
有错误。
5、使用PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name)函数获取
Python函数对象,并检查是否可调用。
+6、使用PyObject *Py_BuildValue(const char *format, ...)函数将C类型的数据结构转换成
Python对象,作为Python函数的参数,没有参数不需要调用
7、使用PyObject *PyObject_CallObject(PyObject *callable, PyObject *args)函数调用
Python函数,并获取返回值。
+8、使用int PyArg_Parse(PyObject *args, const char *format, ...)函数将返回值转换为C类
型,并检查是否有错误,没有返回值时不需要调用。
9、使用void Py_DECREF(PyObject *o)函数释放所有引用的Python对象。
10、结束时调用void Py_Finalize()函数关闭Python解释器。
相关的函数参数说明参考网站(网站左上角输入函数名即可开始搜索):
https://docs.python.org/zh-cn/3/c-api/import.html
#endif#include <Python.h>//包含Python.h头文件,以便使用Python API。
int main()
{Py_Initialize();//使用void Py_Initialize()初始化Python解释器,// 将当前路径添加到sys.path中PyObject *sys = PyImport_ImportModule("sys");//初始化python解释器PyObject *path = PyObject_GetAttrString(sys, "path");PyList_Append(path, PyUnicode_FromString("."));// 导入para模块PyObject *pModule = PyImport_ImportModule("para");if (!pModule){PyErr_Print();printf("Error: failed to load nopara.py\n");}//获取say_funny函数对象PyObject *pFunc = PyObject_GetAttrString(pModule, "say_funny");if (!pFunc){PyErr_Print();printf("Error: failed to load say_funny\n");}//创建一个字符串作为参数char *category = "comedy";PyObject *pArgs = Py_BuildValue("(s)", category);//调用say_funny函数并获取返回值PyObject *pValue = PyObject_CallObject(pFunc, pArgs);if (!pValue){PyErr_Print();printf("Error: function call failed\n");} //将返回值转换为C类型char *result = NULL;if (!PyArg_Parse(pValue, "s", &result)){PyErr_Print();printf("Error: parse failed\n");}//打印返回值printf("pValue=%s\n", result);//释放所有引用的Python对象Py_DECREF(pValue);Py_DECREF(pFunc);Py_DECREF(pModule);//释放所有引用的Python对象Py_Finalize();return 0;
}

这里要注意的是,Py_BuildValue的第一个参数是类型转换:C对应的Python的数据类型转换对应的格式 如下:

C 对应 Python 数据类型格式
在这里插入图片描述
  • 然要编译和运行这个程序,可以使用以下命令(假设使用的是gcc编译器和Python 3.10版本)

gcc para.c -o para -I /usr/include/python3.10 -l python3.10 ./para

–>正常输出

funny
pValue=comedy


欢迎大家一起交流讨论!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/760275.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

springboot企业级抽奖项目业务二(用户模块)

书接上回&#xff0c;梅开二度 开发流程 该业务基于rouyi生成好了mapper和service的代码&#xff0c;现在需要在controller层写接口 实际操作流程&#xff1a; 看接口文档一>controller里定义函数一>看给出的工具类一>补全controller里的函数一>运行测试 接口…

【数据结构】堆和树详解堆和二叉树的实现堆的top-k问题

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;数据结构_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.树概念及结构 1.1 树的概念 2.2 树的相关概念 1.3 树的表示 1.4 树在实际中的运用 2.二叉树的概念及结构 2.1 二叉树的概念…

vue前端解析jwt

vue前端解析jwt 我们可以用在线解析看解析的结果&#xff1a;https://www.lddgo.net/encrypt/jwt-decrypt 但是如果在前端需要解析token&#xff0c;拿到其中的权限信息&#xff0c;可以这样解决。 在线的&#xff1a; 完美解决&#xff1a; 代码&#xff1a; function par…

MySQL | 表的约束

目录 1. 空属性 NULL 2. 默认值 DEFAULT 3. 列描述comment 4. zerofill 5. 主键 PRIMARY KEY 6. 自增长AUTO_INCREMENT 7. 唯一键UNIQUE 8. 外键 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数…

web前端常用标签(html)

1.定义 1.1标签 语法规范&#xff1a;<标签名 属性名"属性值">标签名</标签名> 标签之间可以嵌套 1.2属性 定制元素的行为的。属性是不通用的&#xff0c;每一个标签存在自身的属性。当属性名属性值时&#xff0c;可以只写属性值 2.HTML常用标签 2…

面试笔记——Redis(分布式锁的使用场景及实现原理)

分布式锁的使用场景 资源竞争控制&#xff1a;多个客户端同时访问共享资源时&#xff0c;可以使用分布式锁来控制资源的并发访问&#xff0c;防止多个客户端同时对同一资源进行修改造成数据不一致的问题。 避免重复操作&#xff1a;在分布式环境中&#xff0c;可能会出现多个客…

如何实现手机遥控端关机按钮同时关闭TV端和手机端界面

目前家庭电视机主要通过其自带的遥控器进行操控&#xff0c;实现的功能较为单一。例如&#xff0c;当我们要在TV端搜索节目时&#xff0c;电视机在遥控器的操控下往往只能完成一些字母或数字的输入&#xff0c;而无法输入其他复杂的内容。分布式遥控器将手机的输入能力和电视遥…

基于springboot+vue的智慧生活商城系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

Pytest自动化测试执行环境切换的两种解决方案(超详细)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 痛点分析 在实际企业的项目中&#xff0c;自动化测试的代码往往需要在不同的环境中进行切换&am…

【STL基础】vector、stack、queue、list、pair、map、unordered_map、set、unordered_set(详细讲解)

vector、list、pair、unordered_map、unordered_set、stack、queue 参考文章&#xff1a; &#xff08;1&#xff09;【apollo】泛型编程 与 STL &#xff08;2&#xff09;c stack用法 入门必看 超详细 &#xff08;3&#xff09;C中queue的用法&#xff08;超详细&#xff0c…

C语言关于void类型的指针作为函数形参在使用时需要注意的坑

目录 前言 一、void*指针使用时不同编译器下的处理结果 二、void*指针传递的指针变量进行位运算时&#xff0c;一定要注意强制转换的类型&#xff0c;和值的取值范围 总结 前言 众所周知&#xff0c;void* 指针作为函数形参时&#xff0c;表示可以接受任意类型的参数&#xf…

C语言基础知识点(十七)结构体中只用指针来存储字符串

// 如果需要用结构存储字符串&#xff0c;用字符数组作为成员会比较简单 // 如果需要使用指向char的指针来进行存储&#xff0c;那么需要请求malloc来 // 为字符串分配合适的存储空间#include <stdio.h> #include <string.h> //提供strcpy()\strlen()的原型 #i…

基于FFmpeg混流及录制rtmp直播流

1、什么是混流&#xff1f; 混流就是把多路音视频流合成单流。准确的说&#xff0c;混流应该叫做混音&#xff08;音频流&#xff09;混画面&#xff08;视频流&#xff09; 混流的过程包括解码、混流、编码和推流四个部分。混流这个环节包括做抖动缓冲&#xff0c;目的是把多…

GDPU Java 天码行空4

文章目录 一、实验目的二、实验内容及要求三、实验内容及要求1. 设计AnimalTool工具类&#xff0c;实现eat()函数多态性&#x1f496; AnimalDemo.java&#x1f338; 运行结果 2. 是猫是狗&#x1f496; DuoTaiDemo5.java&#x1f338; 运行结果 3. 太会了&#x1f496; DuoTai…

国内IP地址切换排行榜软件大全

随着互联网的飞速发展&#xff0c;IP地址切换技术在日常工作和生活中扮演着越来越重要的角色。无论是为了网络安全、访问特定地区网站&#xff0c;还是进行市场调研、网络爬虫等&#xff0c;IP地址切换都成为了不可或缺的工具。虎观代理将为您介绍国内较受欢迎的IP地址切换软件…

B004-springcloud alibaba 服务容错 Sentinel

目录 高并发带来的问题服务雪崩效应常见容错方案常见的容错思路隔离超时限流熔断降级 常见的容错组件 Sentinel入门什么是Sentinel微服务项目集成Sentinel核心库安装Sentinel控制台实现一个接口的限流 Sentinel的概念和功能基本概念重要功能 Sentinel规则流控规则三种流控模式三…

深度学习——线性代数相关知识

线性代数基础知识 一、线性代数基础知识1、标量2、向量3、矩阵4、张量5、点积6、向量—矩阵积7、矩阵—矩阵乘法 二、小结 一、线性代数基础知识 本节将介绍简要地回顾一下部分基本线性代数内容&#xff0c;线性代数中的基本数学对象、算术和运算&#xff0c;并用数学符号和相…

基于SpringBoot的高校办公室行政事务管理系统

采用技术 基于SpringBoot的高校办公室行政事务管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 功能清单 教师信息管理 办公室管理 办公物资管…

软文营销应该怎么做?软文营销的关键

软文本营销不是一个简单的写作和发送文章的过程&#xff0c;而是一个从早期准备到软文本写作再到效果评估的综合运营管理过程。 步骤一&#xff1a;目标明确 目标是指目标用户&#xff0c;找出目标用户是什么样的群体&#xff0c;从而根据用户群体的画像进行软文准备。 步骤二…

3000+人使用,这套人力资源数据分析工具还能这么用

中国科学院自动化研究所&#xff08;以下简称“自动化所”&#xff09;成立于1956年&#xff0c;是中国科学院率先布局成立的“人工智能创新研究院”的总体牵头单位&#xff0c;是中国最早开展智能科学与技术基础理论、关键技术和创新性应用研究的科研机构&#xff0c;也是中国…