详解如何在VS2019和VScode中配置C++调用python接口

why

看到这个标题有些人说了,为什么好好的C++你非要调用python?人家明明是两种语言呀!
但是在实际应用中,有时候会用到C/C++调用python来更简单地去完成一些功能,不然人家python为什么有一个文件夹叫include,里边全是.h文件呢?

VScode中配置环境

首先是在VScode中为C++调用python接口配置环境,这里假设你已经配置好了c++编程环境!

1、配置step1

用快捷键Ctrl+Shift+X打开Extensions 商店,输入python,install:

2、配置step2

用快捷键Ctrl+Shift+P打开命令面板,打开C/C++:编辑配置(UI):

然后编辑c_cpp_properties.json文件,在文件中的includePath项添加自己的python include路径:“D:\\Python\\Python37\\include”,注意格式。

{
 "configurations": [
  {
   "name": "Win32",
   "includePath": [
    "${workspaceFolder}/**",
    "D:\\Python\\Python37\\include"
   ],
   "defines": [
    "_DEBUG",
    "UNICODE",
    "_UNICODE"
   ],
   "compilerPath": "D:\\MinGW\\bin\\gcc.exe",
   "cStandard": "c11",
   "cppStandard": "c++17",
   "intelliSenseMode": "clang-x64"
  }
 ],
 "version": 4
}

3、测试

测试一下:编辑hello.py

def printHello():
 print("Hello World")

c++调用python有两种方式,我在代码中都进行了测试,编辑main.cpp

#include "D:\Python\Python37\include\Python.h"
//#include <Python.h>
#include <iostream>
using namespace std;
void cython1()
{
 Py_Initialize();       //初始化python解释器,告诉编译器要用的python编译器
 PyRun_SimpleString("import hello");  //调用python文件
 PyRun_SimpleString("hello.printHello()"); //调用上述文件中的函数
 Py_Finalize();       //结束python解释器,释放资源
}

void cython2()
{
 Py_Initialize();
 PyObject *pModule = NULL;
 PyObject *pFunc = NULL;
 pModule = PyImport_ImportModule("hello");    //这里是要调用的文件名
 pFunc = PyObject_GetAttrString(pModule, "printHello"); //这里是要调用的函数名
 PyEval_CallObject(pFunc, NULL);      //调用函数
 Py_Finalize();
}

int main()
{
 int select;
 cin >> select;
 select == 1 ? cython1():cython2();
 return 0;
}

4、问题汇总(重磅)

1、为什么我包含了Python.h,c++代码中调用也没有报错,但是运行时会出现如下错误?(暂未从根本上解决问题,仿照后面linux上的头文件调用方法也是无效,稍后解决会更新)

main.cpp:2:10: fatal error: Python.h: No such file or directory
 #include "Python.h"
   ^~~~~~~~~~
compilation terminated.

说明没有include成功啊,这里我猜测是由于版本问题导致的,暂未得到解决,但是有一种方式是绝对可以使用的,并且已经在代码中体现了,那就是…直接inlcude绝对路径!

#include "D:\Python\Python37\include\Python.h"

可能心细的朋友已经发现了,你只是包含了头文件,链接库还没有链接啊!但是我当时的心情不允许我这么细心啊,咳咳
这里打个广告!强烈建议各位C/C++ develpoers,去仔细读一下程序员的自我修养这本书,真的受益匪浅。
2、由于没有链接静态库而报错(同上,暂时只有傻瓜式解决办法,使用makefile解决此问题请看我之后的博客:在makefile中链接静态库)

C:\Users\11955\AppData\Local\Temp\ccLmGIL8.o:main.cpp:(.text+0xb): undefined reference to `__imp_Py_Initialize'
C:\Users\11955\AppData\Local\Temp\ccLmGIL8.o:main.cpp:(.text+0x20): undefined reference to `__imp_PyRun_SimpleStringFlags'
C:\Users\11955\AppData\Local\Temp\ccLmGIL8.o:main.cpp:(.text+0x35): undefined reference to `__imp_PyRun_SimpleStringFlags'
C:\Users\11955\AppData\Local\Temp\ccLmGIL8.o:main.cpp:(.text+0x3e): undefined reference to `__imp_Py_Finalize'
C:\Users\11955\AppData\Local\Temp\ccLmGIL8.o:main.cpp:(.text+0x56): undefined reference to `__imp_Py_Initialize'
C:\Users\11955\AppData\Local\Temp\ccLmGIL8.o:main.cpp:(.text+0x76): undefined reference to `__imp_PyImport_ImportModule'
C:\Users\11955\AppData\Local\Temp\ccLmGIL8.o:main.cpp:(.text+0x91): undefined reference to `__imp_PyObject_GetAttrString'
C:\Users\11955\AppData\Local\Temp\ccLmGIL8.o:main.cpp:(.text+0xb0): undefined reference to `__imp_PyEval_CallObjectWithKeywords'
C:\Users\11955\AppData\Local\Temp\ccLmGIL8.o:main.cpp:(.text+0xb9): undefined reference to `__imp_Py_Finalize'

解决办法:链接静态库,我把D:\Python\Python37\libs这个文件夹复制到了工作空间的文件夹下,为了方便链接直链接该文件夹下所有文件。

 g++ -o main .\main.cpp -L .\libs\*
 .\main.exe

VS2019中配置环境

1、step1

首先明确,如果你安装的python是64位的,建议把VS 该项目下的解决方案平台改为x64,并且环境是在特定的解决方案配置下(Debug/Release)进行的,所以不要配置在Debug,却在Release调用Python.h,这样肯定会报错:无法打开Python.h。

2、step2

右键project打开属性,在配置属性 - C/C++ - 常规 - 附加包含目录下添加:

D:\Python\Python37\include

配置属性 - VC++目录 - 库目录下添加:

D:\Python\Python37\libs

3、测试

C++代码和python代码同上,到此我们还没有在VS项目中添加python代码,只需要将hello.py复制到main.cpp所在目录即可。

4、问题汇总

1、如果遇到Link110:无法打开python36_d.lib(或者python**_d.lib),在你的python/libs目录下会发现没有这个静态库文件,这时候最简单的做法就是拷贝复制一份python36.lib,并重命名为python36_d.lib
2、如果出现的错误:

Traceback (most recent call last):
File "<string>", line 1, in <module>
NameError: name 'hello' is not defined

这是由于没有找到hello.py文件,解决方案:在初始化python解释器以后添加以下两行代码,用于指定模块的路径:

PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");

3、如果还有错误,请参考C++调用python

5、完整的cpp代码

//#include "D:\Python\Python37\include\Python.h"
//当然,绝对路径永远不会失效!^o^
#include <Python.h>
#include <iostream>
using namespace std;
void cython1()
{
 Py_Initialize();       //初始化python解释器,告诉编译器要用的python编译器
 PyRun_SimpleString("import sys");
 PyRun_SimpleString("sys.path.append('./')");
 PyRun_SimpleString("import hello");  //调用python文件
 PyRun_SimpleString("hello.printHello()"); //调用上述文件中的函数
 Py_Finalize();       //结束python解释器,释放资源
}

void cython2()
{
 Py_Initialize();
 PyObject* pModule = NULL;
 PyObject* pFunc = NULL;
 PyRun_SimpleString("import sys");
 PyRun_SimpleString("sys.path.append('./')");
 pModule = PyImport_ImportModule("hello");    //这里是要调用的文件名
 pFunc = PyObject_GetAttrString(pModule, "printHello"); //这里是要调用的函数名
 PyEval_CallObject(pFunc, NULL);      //调用函数
 Py_Finalize();
}

int main()
{
 int select;
 cin >> select;
 select == 1 ? cython1() : cython2();
 return 0;
}

Linux中配置环境

其实这一部分有点多余,因为我在VScode下编程也采用gcc/g++编译器,linux与之相同,所以遇到的问题也是一致的,都是没有办法直接#include<Python.h>。以Ubuntu 18.04.4 LTS为例:

1、step1

前提是你已经安装了g++,如果使用g++ -v查看版本无果,采用以下命令安装套件:

sudo apt-get install build-essential

首先查看自己的python版本以及位置,位置用于代码编写调用头文件,版本用于编译g++命令的指示链接库。由于ubuntu18.04自带python3,所以命令中都采用了python3而不是python:

python3 -V
>Python 3.6.9

which python3
>/usr/bin/python3

2、step2

找到版本以及位置,在C++代码中采用绝对路径的方法调用Python.h

#include "/usr/include/python3.6/Python.h"
//或者
#include <python3.6/Python.h>

同时也要在初始化python解释器以后添加以下两行代码,用于指定模块的路径:

Py_Initialize();
PyRun_SimpleString("import sys"); // add 1
PyRun_SimpleString("sys.path.append('./')"); //add 2

3、测试

同样在编译时需要指定静态链接库,不然的话就用makefile吧~
注意python的版本:

g++ -o main main.cpp -lpython3.6m
./main

注意,也可以采用编译时包含头文件的方式,这样就不用在代码中调用头文件了,不推荐(这样的命令我要它有何用):

g++ -o main main.cpp -lpython3.6m -I /usr/include/python3.6
./main

4、疑问

1、为什么VScode不用再代码中指定python文件的路径,而VS和Linux中都需要?
2、为什么在VS2019和Linux中都不用绝对路径就可以调用Python.h文件,而在VScode中却没有作用?
还望与各位朋友探讨。

到此这篇关于详解如何在VS2019和VScode中配置C++调用python接口的文章就介绍到这了,更多相关C++调用python接口内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python调用C++,通过Pybind11制作Python接口

    我是在ubuntu系统进行实验的,所以和window可能会有区别. python调用C/C++有不少的方法,如boost.python, swig, ctypes, pybind11等,这些方法有繁有简,而pybind11的优点是对C++ 11支持很好,API比较简单,现在我们就简单记下Pybind11的入门操作. 1. pybind11简介与环境安装 pybind11是一个轻量级的只包含头文件的库,它主要是用来在已有的 C++代码的基础上做扩展,它的语法和目标非常像Boost.Python,但

  • 详解如何在VS2019和VScode中配置C++调用python接口

    why 看到这个标题有些人说了,为什么好好的C++你非要调用python?人家明明是两种语言呀! 但是在实际应用中,有时候会用到C/C++调用python来更简单地去完成一些功能,不然人家python为什么有一个文件夹叫include,里边全是.h文件呢? VScode中配置环境 首先是在VScode中为C++调用python接口配置环境,这里假设你已经配置好了c++编程环境! 1.配置step1 用快捷键Ctrl+Shift+X打开Extensions 商店,输入python,install:

  • 详解如何在cmd命令窗口中搭建简单的python开发环境

    1.快捷键win+r输入cmd回车调出cmd界面,在命令行输入python回车,显示python命令无法识别 2.登陆python官网https://www.python.org/,选择download页面进去找到python的一个版本下载安装,我用的是python3.4.2 3.找到安装位置,python.exe就是python的解释器,之前在cmd里输入python无法执行,就是因为cmd在默认路径中找不到python命令.D:\Pathon34就是解释器的路径,我们复制这个路径. 4.右击

  • 详解如何在C#/.NET Core中使用责任链模式

    最近我有一个朋友在研究经典的"Gang Of Four"设计模式.他经常来询问我在实际业务应用中使用了哪些设计模式.单例模式.工厂模式.中介者模式 - 都是我之前使用过,甚至写过相关文章的模式.但是有一种模式是我还没有写过文章,即责任链模式. 什么是责任链?# 责任链模式(之前我经常称之为命令链模式)是一种允许以使用分层方式"处理"对象的模式.在维基百科中的经典定义是 在面向对象设计中,责任链模式是一种由命令对象源及其一系列处理对象组成的设计模式.每个处理对象包含了

  • 详解如何在ASP.NET Core中编写高效的控制器

    通过遵循最佳实践,可以编写更好的控制器.所谓的"瘦"控制器(指代码更少.职责更少的控制器)更容易阅读和维护.而且,一旦你的控制器很瘦,可能就不需要对它们进行太多测试了.相反,你可以专注于测试业务逻辑和数据访问代码.瘦控制器的另一个优点是,它更容易维护控制器的多个版本. 这篇文章讨论了使控制器变胖的坏习惯,然后探索了使控制器变瘦和易于管理的方法.我列出编写控制器的最佳实践可能并不全面,但我已经讨论了最重要的一些,并在适当的情况下提供了相关的源代码.在接下来的几节中,我们将研究什么是胖控制

  • 详解如何在ASP.NET Core中使用IHttpClientFactory

    利用IHttpClientFactory可以无缝创建HttpClient实例,避免手动管理它们的生命周期. 当使用ASP.Net Core开发应用程序时,可能经常需要通过HttpClient调用WebAPI的方法以检查终结点是否正常工作.要实现这一点,通常需要实例化HttpClient并使用该实例来调用你的方法.但是直接使用HttpClient也有一些缺点,主要与手动管理实例的生命周期有关. 你可以使用IHttpClientFactory创建HttpClient来避免这些问题.IHttpClie

  • 详解如何在ASP.Net Core中实现健康检查

    健康检查 常用于判断一个应用程序能否对 request 请求进行响应,ASP.Net Core 2.2 中引入了 健康检查 中间件用于报告应用程序的健康状态. ASP.Net Core 中的 健康检查 落地做法是暴露一个可配置的 Http 端口,你可以使用 健康检查 去做一个最简单的活性检测,比如说:检查网络和系统的资源可用性,数据库资源是否可用,应用程序依赖的消息中间件或者 Azure cloud service 的可用性 等等,这篇文章我们就来讨论如何使用这个 健康检查中间件. 注册健康检查

  • 详解如何在ASP.NET Core中使用Route特性

    ASP.NET Core 中的 Route 中间件的职责在于将 request 匹配到各自 Route 处理程序上,Route 分两种:基于约定 和 基本特性 模式. 基于约定 模式的Route采用集中化的方式,而 基于特性 的方式允许你在 Action 或者 Controller 上单独定义,到底采用哪一种可以基于你自己的应用场景,本篇就来讨论如何使用 基于特性 模式. 创建 Controller 类 创建一个 DefaultController 类,新增如下代码. public class

  • 图文详解如何在vue3+vite项目中使用svg

    今天在vue3+vite项目练习中,在使用svg时,发现之前的写法不能用,之前的使用方法参考vue2中优雅的使用svg const req = require.context('./icons/svg', false, /\.svg$/) const requireAll = requireContent => requireContent.keys().map(requireContent) requireAll(req) 然后就各种资料查找,终于实现了,废话不多说,直接上代码: stept1

  • 详解在Java的Struts2框架中配置Action的方法

    在Struts2中Action部分,也就是Controller层采用了低侵入的方式.为什么这么说?这是因为在Struts2中action类并不需要继承任何的基类,或实现任何的接口,更没有与Servlet的API直接耦合.它通常更像一个普通的POJO(通常应该包含一个无参数的execute方法),而且可以在内容定义一系列的方法(无参方法),并可以通过配置的方式,把每一个方法都当作一个独立的action来使用,从而实现代码复用. 例如: package example; public class U

  • 详解如何在ASP.NET Core中使用Redis

    Redis 是一个开源的内存中的数据结构存储系统,可以用作数据库.缓存和消息中间件.它支持多种类型的数据结构:字符串,哈希表,列表,集合,有序集等等. Redis 官方没有推出Windows版本,倒是由Microsoft Open Tech提供了Windows 64bit 版本支持. 如何在Windows机器上安装Redis=>下载安装文件Redis-x64-3.2.100.msi,安装完毕之后,打开service管理器,找到Redis服务,并将其启动.  前期准备: 1.推荐使用Visual

随机推荐