2018-11-25随笔-今天谈谈C++嵌入Python脚本中遇到的问题

由于现在很多底层协议用C/C++,然后机器学习或者深度学习等算法模型使用基于Python的TensorFlow来实现。所以现在C++用来做框架,做软件界面,然后调用Python的算法脚本来进行计算是很常见的需求。

我们的项目中也存在着这样的需求。下面来记录一下相应的实现方式。

背景:C++上用MFC做界面,Python上是import了numpy与pandas模块的处理功能(后续的基于sklearn与TensorFlow的脚本还没嵌入,配置方式相同,后续实验会再放上来)

软件配置:win10/64位+VS2013+Python3.6/64位

  • 在Python的安装目录下,找到libs文件夹,将其中的python36.lib复制一份并命名python36_d.lib,功能是用于VS的调试
  • 在VS中新建项目(随便什么项目,我使用的是控制台程序),在项目-项目属性中设置活动平台为X64,目的是匹配Python的版本
  • 在VS的项目属性里面:C++->常规->附加包含目录,输入..\include
  • 链接器->常规->附加目录项,输入..\libs;链接器->输入->附加依赖项,添加python36.lib;python36_d.lib;
  • python36.dll拷贝到Debug目录下(注意是项目名->X64->debug文件夹里面,与***.exe同目录);将py文件拷贝到Debug目录下(同上)

我的py文件中,需要调用的是其中一个readcase函数,其中需要传入一个文件路径参数,再对文件里面的内容进行相应的处理。

C++代码(这里面我参考了网上的一些案例,上上了一些注释-_-||,需要注意的点我在后面再补充)

 1 #include <iostream>
 2 #include <Python.h>
 3 using namespace std;
 4
 5 extern "C"
 6 {
 7 #include "Python.h"
 8 }
 9 //调用输出"Hello Python"函数
10 void Hello()  //没有传参的话就没啥问题
11 {
12     Py_SetPythonHome(L"G:\Python3.6.3_ 64");
13     Py_Initialize();//调用Py_Initialize()进行初始化
14     PyObject * pModule = NULL; //声明在C++中的用到的Python变量
15     PyObject * pFunc = NULL;
16     pModule = PyImport_ImportModule("c_usepython");//调用的Python文件名,test_Ctopython
17     pFunc = PyObject_GetAttrString(pModule, "Hello");//调用的函数名
18     PyEval_CallObject(pFunc, NULL);//调用函数,NULL表示参数为空
19     Py_Finalize();//调用Py_Finalize,和Py_Initialize相对应的.
20 }
21 //调用Add函数,传两个int型参数
22 void Add()  //测试传参的例子,
23 {
24     Py_SetPythonHome(L"G:\Python3.6.3_ 64");
25     Py_Initialize();
26     PyObject * pModule = NULL;
27     PyObject * pFunc = NULL;
28     pModule = PyImport_ImportModule("c_usepython");//Python文件名
29     pFunc = PyObject_GetAttrString(pModule, "Add");//Add:Python文件中的函数名
30     //创建参数:
31     PyObject *pArgs = PyTuple_New(2);//函数调用的参数传递均是以元组的形式打包的,2表示参数个数
32     PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 6));//0--序号,i表示创建int型变量
33     PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 8));//1--序号
34     //返回值
35     PyObject *pReturn = NULL;
36     pReturn = PyEval_CallObject(pFunc, pArgs);//调用函数
37     //将返回值转换为int类型
38     int result;
39     PyArg_Parse(pReturn, "i", &result);//i表示转换成int型变量
40     cout << "6 + 8 = " << result << endl;
41     //Py_Finalize();
42 }
43 void Readcase2()  //
44 {     /
45     char* picpath = "D:\\file111.dat";//需要读取的路径参数,这里的路径太长就一直无法正常运行,C++里面没有报错,但是调用老是失败,返回py里面的threading assert tlocked()错误,我觉得是因为参数没有传进去,Python才报错
46     cout<<picpath<<endl;
47     Py_SetPythonHome(L"G:\Python3.6.3_ 64");
48     Py_Initialize();
49     //PyEval_InitThreads(); //初始化进程
50     PyObject * pModule = NULL;
51     PyObject * pFunc = NULL;
52     PyObject* pRetVal = NULL;
53     //PyObject * pArgs=NULL ;
54     pModule = PyImport_ImportModule("c_usepython");//Python文件名
55     pFunc = PyObject_GetAttrString(pModule, "readcase");//Python文件中的函数名
56     //创建参数:
57     PyObject *pArgs = PyTuple_New(1);//函数调用的参数传递均是以元组的形式打包的,2表示参数个数
58     PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", picpath));//0--序号,i表示创建int型变量
59     //pArgs = PyTuple_New(1);
60     //PyTuple_SetItem(pArgs,0,Py_BuildValue("s", "G:\\实验室工作\\CT项目软件工作\\75-1-dao"));//这个字符串太长了,导致调用失败
61     //PyObject *pReturn = NULL; //我这个函数不需要返回,具体工作都在Python里面做了,以后会返回数组来进行下一步工作
62     //PyGILState_STATE gstate;  //这个是关于GIL的一些内容,具体功能不太了解,当初调试的时候失败,似乎没啥用
63     //gstate = PyGILState_Ensure();
64     //PyEval_CallObject(pFunc, pArgs);
65     PyEval_CallObject(pFunc, pArgs);//调用函数,PyObject_CallObject()这个函数也可以,两者功能很相似
66     //PyGILState_Release(gstate);
67     //将返回值转换为int类型
68     //char result;
69     //PyArg_Parse(pReturn, "s", &result);//s表示转换成string型变量
70     //cout << "结果: " << result << endl;
71     Py_Finalize();
72 }
73 int main(int argc, char** argv)
74 {
75     //cout << "调用Test001.py中的Hello函数..." << endl;
76     ////Hello();
77     //cout << "\n调用Test001.py中的Add函数..." << endl;
78     //Add();
79     cout << "\n尝试调用test_Ctopython中的readcase文件..." << endl;
80     Readcase2();
81     system("pause");
82     return 0;
83 }

结果能跑起来,暂时先这样吧,想到什么再说吧。后面的TensorFlow实验,有时间做了再上传。

原文地址:https://www.cnblogs.com/ddl-2018/p/10017612.html

时间: 2024-10-10 11:02:25

2018-11-25随笔-今天谈谈C++嵌入Python脚本中遇到的问题的相关文章

freeswitch嵌入python脚本

操作系统:debian8.5_x64 freeswitch 版本 : 1.6.8 python版本:2.7.9 开启python模块 安装python lib库 apt-get install python-dev 编辑modules.conf,开启python模块: languages/mod_python 编译安装: ./configure && make && make install 在modules.conf.xml中开启python支持: 启动freeswitc

在C语言中如何嵌入python脚本

最近在写配置文件时,需要使用python脚本,但脚本是一个监控作用,需要它一直驻留在linux中运行,想起C语言中能够使用deamon函数来保留一个程序一直运行,于是想到写一个deamon,并在其中嵌入python脚本. 上网查一下,发现确实有办法做到,下面亲测有效: #include <Python.h> #include <stdio.h> int main() { Py_Initialize(); PyRun_SimpleString("print 'Hello P

2018.11.25日脉象记录

2018.11.22日改方子 变化: 柴胡从9克减为6克                 //感冒的症状减退? 天花粉15克加到30克 //这四个变化的原因都是附子+党参导致的血热,出汗,血亏,水少 大枣从45克增加到60克 //停止茯苓排水,增加大枣补血,生蒲黄凉血,继续疏通经络 茯苓12克减为0克   //左右手整体脉象变成洪大中空,说明热损耗了津液 生蒲黄9克,凉血   //天花粉增量是消除肺中积聚的热,肾虚第一就要保肺,使得肺能降雨给肾,补肾阴 增加: 炒芥子9克 归肺经,温中散寒,利气

2018.11.25 齐鲁工业大学ACM-ICPC迎新赛正式赛题解

整理人:周翔 A 约数个数(难) 解法1:苗学林  解法2:刘少瑞   解法3:刘凯 B Alice And Bob(易) 解法1:周翔  解法2:苗学林  解法3:刘少瑞 C 黑白黑(易) 解法:苗学林 D GPA(易) 解法:周翔 E are you ok?(易) 解法:苗学林 F 折纸达人(难) 解法:苗学林 G 数数(易) 解法:周翔 H 神奇老虎木几(中) 解法:刘少瑞 I 五环(易) 解法:周翔 J 开挂的小洋(易) 解法:苗学林 K 数字匹配(中) 解法:苗学林 L 寄蒜几盒?(难

工程脚本插件方案 - c集成Python基础篇(VC++嵌入Python)

序: 为什么要集成脚本,怎么在工程中集成Python脚本. 在做比较大型的工程时,一般都会分核心层和业务层.核心层要求实现高效和稳定的基础功能,并提供调用接口供业务层调用的一种标准的框架划分.在实际中根据需求会拆分的更细.外部的表现形式就是一个核心动态库,带着一堆业务业务动态库.通过一个调度程序把这些链接起来,外加一堆配置文件,就形成一个完成的项目. 这种模式在一个团队开发中,工作职责比较容易划分.制定API接口后,开发工作基本可以并行实现,包括后期的功能测试(白盒.黑盒).不管工程使用什么语言

利用ngx_python模块嵌入到Python脚本

导读 Python是一种计算机程序设计语言.是一种动态的.面向对象的脚本语言,最初被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新功能的添加,越来越多被用于独立的.大型项目的开发. ngx_python 是为 nginx 嵌入 python 脚本的模块. 环境 - python 2.7.* - nginx-1.6.3+ 安装 git clone https://github.com/rryqszq4/ngx_python.git wget 'http://nginx.org/d

日本IT行业劳动力缺口达22万 在日中国留学生迎来就业好时机 2017/07/18 11:25:09

作者:倪亚敏 来源:日本新华侨报 发布时间:2017/07/18 11:25:09   据日本政府提供的数据,日本2018年应届毕业生的"求人倍率"已经达到了1.78倍.换言之,就是100名大学生里有178个就业岗位可选择,即使所有大学毕业生都进入劳动力市场,也还有78个岗位空缺.劳动力现状是寒冷冬天,而学生们确实迎来了就业春天. 在众多岗位当中,日本的信息技术(IT)领域采用的外国人留学生最多.去年,已经在日本企业就职的留学生当中(除去制造行业),27.3%的毕业生进入了IT行业.根

2018.4.25 18周1次课

十八周一次课(4月25日) 20.27 分发系统介绍 20.28 expect脚本远程登录 20.29 expect脚本远程执行命令 20.30 expect脚本传递参数 20.27 分发系统介绍 expect是一种能够按照脚本内容里面设定的方式与交互式程序进行"会话"的程序.根据脚本内容,Expect可以知道程序会提示或反馈什么内容以及什么是正确的应答.它是一种可以提供"分支和嵌套结构"来引导程序流程的解释型脚本语言. 我们熟知的shell编程功能虽然很强大,但是

【谜客帝国】第142届出来混饭的主擂谜会(2018.11.30)

[谜客帝国]第142届出来混饭的主擂谜会(2018.11.30) 主持:瓷  计分:默沫 1.莫明其妙(礼貌用语)晚上好 2.漂泊母牵挂(字)嗨 3.一双玉臂千人枕(新称谓)女博客 4.半点朱唇万客尝(成语)任人唯亲 5.一场秋雨一场凉(医学名词)渐冻人 6.残月如弓,星星双映(字)弱 7.母亲伴内戚,端午西湖游(市名)上海 8.一心求平安(字)恙 9.二月伴儿游古迹(中药)元胡 10.“骑赤兔,提青偃,过五关,斩六将”(军用名词二 2+4)马刀,战斗减员 11.书法比赛(建筑名词)品字形结构