C++调用python: VS2017 + Anaconda + pypi第三方库

步骤一:在Anaconda中创建虚拟环境

        这一点对大家来说应该很简单,简单介绍一下,不做过多解释。值得注意的是,要用conda命令创建环境,用pip install配置环境。

conda create -n c_python_env python==3.9 # 用conda创建python虚拟环境
conda activate c_python_env              # 激活该虚拟环境
pip install numpy                        # 在虚拟环境中用pip安装python包

在Anaconda的安装目录下,可以看到如下文件夹,就是我们新创建的环境:

步骤二:在VS2017中,创建一个C++项目: C_Python

        具体过程不再赘述,在项目中创建一个文件“c_python_test.cpp”,添加以下内容:

c_python_test.cpp

#include <Python.h>
#include <iostream>
#include <string>
using namespace std;int main_()
{	//1. 初始化Py_Initialize();//使用python之前,要调用Py_Initailize()函数,进行初始化if (!Py_IsInitialized){printf("初始化失败!!");return 0;}PyRun_SimpleString("print('hello world')");PyRun_SimpleString("import numpy as np");Py_Finalize();system("pause");return 0;
}

 步骤三:在VS2017中配置Anaconda创建的python环境

VS2017的设置如下:

        1)在VS的项目属性>>配置属性>>VC++目录>>包含目录中,将Anaconda虚拟环境的根目录下的include文件夹添加进来;

        2)在VS的项目属性>>配置属性>>VC++目录>> 库目录中,将Anaconda虚拟环境的根目录下的libs文件夹添加进来

         3)然后在VS的项目属性>>配置属性>>链接器>>输入>>附加依赖项中,Anaconda虚拟环境的根目录下的libs/python39_d.lib添加上。如果没有python39_d.lib文件,就把python39.lib复制一份,重命名为python39_d.lib。

 4)拷贝Anaconda虚拟环境的根目录下的“DLLs”和“Lib”两个文件夹复制到exe所在文件夹(x64/Release)。没有exe文件夹就先编译生成一个。这一步很重要,否则C++无法找到虚拟环境中的第三方依赖库,比如我们上面安装的numpy库。

     

拷贝到

      

        5)如果有必要,把Anaconda虚拟环境中的python3.lib、python39.lib和python39_d.lib也拷贝到exe所在文件夹(x64/Release)。再一次,如果环境中没有python39_d.lib文件,就把python39.lib复制一份,重命名为python39_d.lib。(在我的测试中,这一步不执行也没问题)

拷贝到:

 步骤四: 在VS2017中,生成并运行项目

得到以下输出,表示设置成功。 

升级--步骤五:创建python工程py_script,C++引入python脚本

        假设python脚本的绝对路径为D:/wzg_projects/C_Python/py_script(具体在哪里无所谓)。创建以下两个python脚本

demo.py

import numpy as np def formula1(A,F):print(A,F)return np.array(A*F)

 hello.py

import demo as d def func(a,b):num = d.formula1(10,20)print("result = {}".format(num))print("hello world")

在VS2017中,更改 c_python_test.cpp 脚本的内容:

c_python_test.cpp


#include <iostream>
#include <Python.h>
#include <string>
using namespace std;int main_()
{// 1. 开始python与c++的接口模块,初始化。Py_Initialize();//使用python之前,要调用Py_Initailize()函数,进行初始化if (!Py_IsInitialized()){printf("python与c++的接口模块初始化失败");return 0;}// 2. 可行性的基础验证,测试成功后可注释掉//PyRun_SimpleString("print('hello world')");//PyRun_SimpleString("import numpy as np");// 3. 添加python脚本的搜索路径PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.append('D:/wzg_projects/C_Python/py_script')");// 4. 定义pythonObject类对象,并实例化,前向计算PyObject* pModule = NULL;PyObject* pFunc = NULL;// 1)pModule实例化pModule = PyImport_ImportModule("hello");//通过python文件名寻找python脚本,文件名不用加后缀,把python脚本编码为c++格式if (pModule == NULL)  // 如果找不到文件就报错{cout << "没找到python脚本:hello.py" << endl;return 0;}// 2) pFunc 实例化pFunc = PyObject_GetAttrString(pModule, "func");//从pModule脚本中提取名字为“func”的函数,封装为c++格式的pFunc函数if (!pFunc || !PyCallable_Check(pFunc)) {cout << "没找到python函数:func" << endl;return 0;}// 3) 把C++变量转变成Python格式//    i) 参变量的定义方式1//PyObject* pArgs = Py_BuildValue("ii", 25, 6); // 定义函数的参变量。"ii"表示定义两个int类型的变量。还有许多其他格式,可以具体情况具体改变。//    ii) 参变量的定义方式2--推荐使用PyObject* pArgs = PyTuple_New(2);PyTuple_SetItem(pArgs, 0 ,Py_BuildValue("i", 25)); // 把一个int类型的数据“25”放在python tuple的索引为0的位置。PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 6)); // 把一个int类型的数据“25”放在python tuple的索引为0的位置。// 4) 运行python函数PyObject* pReturn = PyObject_CallObject(pFunc, pArgs); // 运行python函数,计算函数的输出结果。把参数args2输入到函数pFunc中,计算输出结果,存储到pRet中。// 5. 把python格式的数据转变成c++格式int cReturn = 0;PyArg_Parse(pReturn, "i", &cReturn);//注意:PyArg_Parse的最后一个参数,必须加上“&”符号。“i”表示转变成int类型的变量。cout << "cReturn:" << cReturn << endl;// 6. 结束python与c++的接口模块Py_Finalize();system("pause");return 0;
}

        重新生成项目,运行,可以实现对python脚本的调用。具体如何调用,请看上面的代码,注释还是比较详细的。

提示与思考:

  1.  如果python脚本中存在bug,无法运行,或找不到依赖库,c++脚本仍旧可以顺利编译成功,但是在运行时会提示无法找到python文件,比如无法找到上面的“hello.py”
  2. 步骤三中的过程----拷贝Anaconda虚拟环境的根目录下的“DLLs”和“Lib”两个文件夹复制到exe所在文件夹(x64/Release)。没有exe文件夹就先编译生成一个。这一步很重要,否则C++无法找到虚拟环境中的第三方依赖库,比如我们上面安装的numpy库。 这一步不可省略。经试验,把这两个文件夹添加到vs2017的库目录中,也无法解决这个问题。
  3. 在步骤五的c_python_test.cpp脚本中,需要设置python脚本的寻找路径,防止C++找不到python脚本。为了未来的可扩展性、易用性和可移植性,或许这一步可以通过cmake、qt等方式以自动化的方式解决。
  4. 应该编写一个接口函数,用于c++和python相互传递参数,并把这个函数固定下来。
  5. linux环境下,没有vs2017,应该如何设置c++的python依赖库呢?用cmake编译好?

 

参考及进一步学习:

[1] C++调用python方法及环境配置(Windows环境、VS工具)

[2] C++调用Python遇到的问题总结(anaconda的虚拟环境、使用python第三方库,如pytorch、pytorch geometric) [3] C++调用Python(混合编程)函数整理总结

[4] C++调用python脚本 

[5] C/C++ 调用Python 

[6] C++调用python 之 环境配置(VS2015 + anaconda)

[7] C++调用python文件(包含第三方库) 

更多扩展教程:

[1]  图像处理深度学习python代码改写成c++推理

[2] python调用C++中的函数【最简明教程】 

[3] [pybind11]为c++项目写python API接口 - 知乎 

[4] C++和python的代码如何相互调用? - 知乎 

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

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

相关文章

在ubuntu虚拟机上安装不同版本的交叉编译工具链

在之前的章节中&#xff0c;学习了如何安装了4.8.3的交叉编译工具链&#xff1a; 交叉编译 和 软硬链接 的初识&#xff08;面试重点&#xff09;-CSDN博客 但是&#xff0c;在之后学习内核编译时&#xff0c;由于我的树莓派内核版本较高&#xff0c;为6.1&#xff0c;所以在…

Java SpringBoot Controller常见写法

文章目录 环境Controller调用脚本运行结果总结 环境 系统: windows 11 工具: java, idea, git bash Controller 接口常见有以下几种方式 其中&#xff1a; Tobj 调用脚本 我的是windows 系统&#xff0c;使用 git bash 窗口运行, 用 cmd 或者 power shell 会有问题 curl …

传统算法:使用 Pygame 实现二分查找

使用 Pygame 模块实现了二分查找的动画演示。首先,它生成一个有序数组,并通过 Pygame 在屏幕上绘制这个数组的条形图。接着,通过二分查找算法对有序数组进行查找,动画效果可视化每一步的变化。在查找的过程中,程序通过比较目标值和数组中间元素,逐步缩小搜索范围,高亮显…

使用 SDKMAN 管理多版本本地 Java 环境---Centos8 Windows

文章目录 windows 安装centos8 安装卸载sdkman使用 windows 安装 SDKMAN是一个 jdk 多版本管理工具&#xff0c;类似于 nodejs 中的 nvm。可以在本地存在多个 java 环境&#xff0c;快速切换功能&#xff0c;同时&#xff0c;他不止于 java sdk&#xff0c;还有maven、tomcat等…

如何安装RAD Studio 12(delphi 12)

如何安装RAD Studio 12&#xff08;delphi 12&#xff09; RAD Stuido 12 Athens How to install RAD Studio 12 29.0.50491.5718 InterBase 2020 14.5.0.864(x64) 14.5.0.864(x86) Download: http://altd.embarcadero.com/download/radstudio/12.0/RADStudio_12_0_49157…

血的教训---入侵redis并免密登录redis所在服务器漏洞复现

血的教训—入侵redis并免密登录redis所在服务器漏洞复现 今天就跟着我一起来入侵redis并免密登录redis所在服务器吧&#xff0c;废话不多说&#xff0c;我们直接开始吧。 这是一个体系的学习步骤&#xff0c;当然如果基础扎实的话可以继续往下面看 以下都是关联的文章&#xff…

华为云之一键安装宝塔面板

华为云之一键安装宝塔面板 一、本次实践介绍1.1 实践环境简介1.2 本次实践目的 二、宝塔面板介绍三、环境准备工作3.1 预置实验环境3.2 查看环境信息3.3 登录华为云3.4 查看弹性云服务器状态3.5 ssh登录弹性云服务器3.6 查看操作系统版本 四、安装宝塔面板4.1 一键部署宝塔面板…

【古月居《ros入门21讲》学习笔记】05_ROS是什么及其核心概念

目录 说明 1. ROS发展史 ROS版本演变 2. ROS是什么 ROS中的通信机制 ROS中的开发工具 ROS中的应用功能 ROS中的生态系统 3. ROS核心概念 节点与节点管理器 通信方式1&#xff1a;话题 通信方式2&#xff1a;服务 话题与服务的区别 参数 文件系统 说明 1. 本系列…

深入理解Zookeeper系列-2.Zookeeper基本使用和分布式锁原理

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring源码、JUC源码、Kafka原理、分布式技术原理&#x1f525;如果感觉博主的文章还不错的话&#xff…

nginx部署多个vue或react项目

下载nginx(tar.gz) nginx: download(官方地址) 部署nginx # 进入nginx压缩包所在目录 cd /usr/nginx# 解压 tar -zxvf nginx-1.25.3.tar.gz# 安装nginx的相关依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel# 生成Makefile可编译文件 cd /usr/ng…

flutter开发实战-轮播Swiper更改Custom_layout样式中Widget层级

flutter开发实战-轮播Swiper更改Custom_layout样式中Widget层级 在之前的开发过程中&#xff0c;需要实现卡片轮播效果&#xff0c;但是卡片轮播需要中间大、两边小一些的效果&#xff0c;这里就使用到了Swiper。具体效果如视频所示 添加链接描述 这里需要的效果是中间大、两边…

No matching version found for @babel/compat-data@^7.23.5 处理

npm ERR! notarget No matching version found for babel/compat-data^7.23.5 处理 报错信息 npm WARN ERESOLVE overriding peer dependency npm ERR! code ETARGET npm ERR! notarget No matching version found for babel/compat-data^7.23.5. npm ERR! notarget In most …