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
#include
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 "", line 1, in
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
#include
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。以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
同时也要在初始化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接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!