詳解如何在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,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介面內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!