如何在C++中調(diào)用Python_第1頁
如何在C++中調(diào)用Python_第2頁
如何在C++中調(diào)用Python_第3頁
如何在C++中調(diào)用Python_第4頁
如何在C++中調(diào)用Python_第5頁
已閱讀5頁,還剩7頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第如何在C++中調(diào)用Python為了使用Python.h這個(gè)擴(kuò)展項(xiàng),我們需要安裝一個(gè)python*-dev而不是python*,這兩者略有區(qū)別,下面的案例展示的是在Ubuntu20.04下安裝python3.9-dev的方法:

dechin@ubuntu2004:~/projects/gitlab/dechin/$sudoaptinstallpython3.9-dev

正在讀取軟件包列表...完成

正在分析軟件包的依賴關(guān)系樹

正在讀取狀態(tài)信息...完成

下列軟件包是自動(dòng)安裝的并且現(xiàn)在不需要了:

chromium-codecs-ffmpeg-extragstreamer1.0-vaapi

libgstreamer-plugins-bad1.0-0linux-headers-5.8.0-43-generic

linux-hwe-5.8-headers-5.8.0-43linux-image-5.8.0-43-generic

linux-modules-5.8.0-43-genericlinux-modules-extra-5.8.0-43-generic

使用'sudoaptautoremove'來卸載它(它們)。

將會(huì)同時(shí)安裝下列軟件:

libexpat1-devlibpython3.9libpython3.9-devzlib1g-dev

下列【新】軟件包將被安裝:

libexpat1-devlibpython3.9libpython3.9-devpython3.9-devzlib1g-dev

升級(jí)了0個(gè)軟件包,新安裝了5個(gè)軟件包,要卸載0個(gè)軟件包,有30個(gè)軟件包未被升級(jí)。

需要下載6,613kB的歸檔。

解壓縮后會(huì)消耗28.7MB的額外空間。

您希望繼續(xù)執(zhí)行嗎?[Y/n]Y

獲取:1/ubuntufocal/mainamd64libexpat1-devamd642.2.9-1build1[116kB]

獲取:2/ubuntufocal-updates/universeamd64libpython3.9amd643.9.0-5~20.04[1,710kB]

獲取:3/ubuntufocal-updates/universeamd64libpython3.9-devamd643.9.0-5~20.04[4,119kB]

獲取:4/ubuntufocal-updates/mainamd64zlib1g-devamd641:1.2.11.dfsg-2ubuntu1.2[155kB]

獲取:5/ubuntufocal-updates/universeamd64python3.9-devamd643.9.0-5~20.04[512kB]

已下載6,613kB,耗時(shí)4秒(1,594kB/s)

正在選中未選擇的軟件包libexpat1-dev:amd64。

(正在讀取數(shù)據(jù)庫...系統(tǒng)當(dāng)前共安裝有269544個(gè)文件和目錄。)

準(zhǔn)備解壓.../libexpat1-dev_2.2.9-1build1_amd64.deb...

正在解壓libexpat1-dev:amd64(2.2.9-1build1)...

正在選中未選擇的軟件包libpython3.9:amd64。

準(zhǔn)備解壓.../libpython3.9_3.9.0-5~20.04_amd64.deb...

正在解壓libpython3.9:amd64(3.9.0-5~20.04)...

正在選中未選擇的軟件包libpython3.9-dev:amd64。

準(zhǔn)備解壓.../libpython3.9-dev_3.9.0-5~20.04_amd64.deb...

正在解壓libpython3.9-dev:amd64(3.9.0-5~20.04)...

正在選中未選擇的軟件包zlib1g-dev:amd64。

準(zhǔn)備解壓.../zlib1g-dev_1%3a1.2.11.dfsg-2ubuntu1.2_amd64.deb...

正在解壓zlib1g-dev:amd64(1:1.2.11.dfsg-2ubuntu1.2)...

正在選中未選擇的軟件包python3.9-dev。

準(zhǔn)備解壓.../python3.9-dev_3.9.0-5~20.04_amd64.deb...

正在解壓python3.9-dev(3.9.0-5~20.04)...

正在設(shè)置libpython3.9:amd64(3.9.0-5~20.04)...

正在設(shè)置libexpat1-dev:amd64(2.2.9-1build1)...

正在設(shè)置zlib1g-dev:amd64(1:1.2.11.dfsg-2ubuntu1.2)...

正在設(shè)置libpython3.9-dev:amd64(3.9.0-5~20.04)...

正在設(shè)置python3.9-dev(3.9.0-5~20.04)...

正在處理用于man-db(2.9.1-1)的觸發(fā)器...

正在處理用于libc-bin(2.31-0ubuntu9.2)的觸發(fā)器...

安裝完成后,如果在當(dāng)前命令行下運(yùn)行python3.9,是可以看到一個(gè)python專屬的命令行界面的,可以通過exit()退出。但是我們這里側(cè)重的是跟C++的配合工作,因此我們更加關(guān)注lib和include目錄下是否有生成相關(guān)的目錄,可以執(zhí)行如下指令進(jìn)行查看:

dechin@ubuntu2004:~/projects/gitlab/dechin/$ll/usr/lib/|greppython

drwxr-xr-x26rootroot204805月716:27python2.7/

drwxr-xr-x3rootroot40962月1002:47python3/

drwxr-xr-x30rootroot204805月716:30python3.8/

drwxr-xr-x31rootroot122885月2016:31python3.9/

這里我們看到有一個(gè)3.9的版本,也就是我們剛才安裝的版本,再看看include下的目錄:

dechin@ubuntu2004:~/projects/gitlab/dechin/$ll/usr/include/|greppython

drwxr-xr-x2rootroot40965月716:31python3.8/

drwxr-xr-x4rootroot40965月2016:31python3.9/

這里我們就可以看到一些區(qū)別了,有一些版本的python不一定會(huì)有這兩個(gè)目錄,但是只有具備了這兩個(gè)目錄,才能夠被C++調(diào)用。

VSCode配置

這里我們使用的IDE是VSCode,但是上述提到的幾個(gè)路徑,在VSCode中默認(rèn)是不被包含的,因此在代碼編輯的過程中在includePython.h這一步就會(huì)報(bào)錯(cuò)了。這一章節(jié)的目的主要是解決IDE中的報(bào)錯(cuò)問題,還不是最終運(yùn)行中出現(xiàn)的問題,因?yàn)檫\(yùn)行時(shí)我是通過命令行執(zhí)行g(shù)++來運(yùn)行的,而不是直接用IDE來跑。首先在VSCode界面上按順序同時(shí)按?。篶trl+shift+P,在彈出的窗口中輸入C/C++EditConfigurations(JSON)查找相關(guān)JSON配置文件,在列表中點(diǎn)擊后會(huì)自動(dòng)在VSCode中打開這個(gè)配置文件:

"configurations":[

"name":"Linux",

"includePath":[

"${workspaceFolder}/**"

"defines":[],

"compilerPath":"/usr/bin/gcc",

"cStandard":"gnu17",

"cppStandard":"c++11",

"intelliSenseMode":"linux-gcc-x64"

"version":4

}

我們所需要做的工作就是,在這個(gè)includePath中把相關(guān)的路徑都加上,比如我這邊添加的路徑是以下3個(gè):

"configurations":[

"name":"Linux",

"includePath":[

"${workspaceFolder}/**",

"/usr/include/python3.9/",

"/usr/lib/python3.9/",

"/usr/include/python3.9/cpython/"

"defines":[],

"compilerPath":"/usr/bin/gcc",

"cStandard":"gnu17",

"cppStandard":"c++11",

"intelliSenseMode":"linux-gcc-x64"

"version":4

}

添加后,includePython.h就不會(huì)顯示報(bào)錯(cuò)了。

HelloWorld測(cè)試

行業(yè)潛規(guī)則,我們先用C++來調(diào)用一個(gè)Python的打印函數(shù),輸出HelloWorld試試:

//cp.cpp

#includePython.h

intmain(intargc,char*argv[]){

Py_Initialize();

PyRun_SimpleString("print('helloworld')\n");

Py_Finalize();

return0;

}

這里需要注意的是一個(gè)運(yùn)行方式,我們是用g++來進(jìn)行編譯的,但是g++默認(rèn)是找不到我們剛才在IDE中所設(shè)定的幾個(gè)includePath的,因此需要我們手動(dòng)在編譯的時(shí)候加上幾個(gè)參數(shù)。這些參數(shù)其實(shí)也可以運(yùn)行python3.9-config去一個(gè)一個(gè)查看,這里我們直接推薦一種可以運(yùn)行成功的參數(shù),其中最重要的是-I和-l這兩個(gè)路徑一定要包含:

dechin@ubuntu2004:~/projects/gitlab/dechin/$g++-ocpycp.cpp-lm-std=c++11-I/usr/include/python3.9/-lpython3.9

dechin@ubuntu2004:~/projects/gitlab/dechin/$ll

總用量4697388

drwxrwxr-x2dechindechin40965月2017:10./

drwxrwxr-x8dechindechin40965月1915:32../

-rw-rw-r--1dechindechin1525月2017:04cp.cpp

-rwxrwxr-x1dechindechin167765月2017:10cpy*

運(yùn)行完成后,就會(huì)在當(dāng)前目錄下生成一個(gè)剛才指定的名字cpy的一個(gè)可執(zhí)行文件,如果是windows系統(tǒng),則會(huì)生成一個(gè)cpy.exe的文件。讓我們執(zhí)行這個(gè)文件:

dechin@ubuntu2004:~/projects/gitlab/dechin/$./cpy

helloworld

成功打印HelloWorld,又離成功更近了一步。

調(diào)用Python函數(shù)string.split()

在C++中如果我們想分割一個(gè)字符串,雖然說也是可以實(shí)現(xiàn)的,但是應(yīng)該沒有比Python中執(zhí)行一個(gè)string.split()更加方便快捷的方案了,因此我們測(cè)試一個(gè)用C++調(diào)用Python的split函數(shù)的功能。

第一次嘗試

一開始我們是寫了這樣一個(gè)簡(jiǎn)單的案例,用PyImport_ImportModule方法去調(diào)用pysplit這個(gè)python模塊:

//cp.cpp

#includePython.h

#includeiostream

usingnamespacestd;

intmain(intargc,char*argv[])

Py_Initialize();

if(!Py_IsInitialized())

cout"Initializefailed!"endl;

return0;

PyObject*pModule=NULL;

PyObject*pFunc;

PyRun_SimpleString("importos");

PyRun_SimpleString("os.system('pwd')");

pModule=PyImport_ImportModule("pysplit");

if(pModule==NULL)

cout"ModuleNotFound!"endl;

//pFunc=PyObject_GetAttrString(pModule,"sp");

//PyObject*args=Py_BuildValue("s","TestStringHelloEveryOne!");

//PyObject*pRet=PyObject_CallObject(pFunc,args);

stringcList[10];

//PyArg_Parse(pRet,"[items]",cList);

cout"res:"cListendl;

Py_Finalize();

return0;

}

對(duì)應(yīng)的Python模塊的內(nèi)容為:

#pysplit.py

defsp(string):

returnstring.split()

這是一個(gè)非常簡(jiǎn)單的函數(shù),但是我們?cè)谡{(diào)用的時(shí)候就直接返回了一個(gè)錯(cuò)誤:

dechin@ubuntu2004:~/projects/gitlab/dechin/$g++-ocpycp.cpp-lm-std=c++11-I/usr/include/python3.9/-lpython3.9./cpy

['pysplit.py','cpy','cp.cpp']

ModuleNotFound!

res:0x7ffc622ae900

這個(gè)錯(cuò)誤是說,找不到pysplit這個(gè)模塊。但是我們同時(shí)借助于PyRun_SimpleString調(diào)用了Python中的os庫,執(zhí)行了一個(gè)查看路徑和當(dāng)前路徑下文件的功能,我們發(fā)現(xiàn)這個(gè)C++文件和需要引入的pysplit.py其實(shí)是在同一個(gè)路徑下的,這就很奇怪了沒有導(dǎo)入成功。

第二次嘗試

經(jīng)過一番的資料查詢,最后發(fā)現(xiàn),即使是在相同的路徑下,也需要通過Python的sys將當(dāng)前目錄添加到系統(tǒng)路徑中,才能夠識(shí)別到這個(gè)模塊,同樣也是使用PyRun_SimpleString的函數(shù):

//cp.cpp

#includePython.h

#includeiostream

usingnamespacestd;

intmain(intargc,char*argv[])

Py_Initialize();

if(!Py_IsInitialized())

cout"Initializefailed!"endl;

return0;

PyObject*pModule=NULL;

PyObject*pFunc;

PyRun_SimpleString("importsys");

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

pModule=PyImport_ImportModule("pysplit");

if(pModule==NULL)

cout"ModuleNotFound!"endl;

pFunc=PyObject_GetAttrString(pModule,"sp");

PyObject*args=Py_BuildValue("s","TestStringHelloEveryOne!");

PyObject*pRet=PyObject_CallObject(pFunc,args);

stringcList[10];

//PyArg_Parse(pRet,"[items]",cList);

cout"res:"cListendl;

Py_Finalize();

return0;

}

這個(gè)也可以理解,Python中的函數(shù)調(diào)用,輸入?yún)?shù)都被打包成了一個(gè)tuple格式,比如**args,而類似**kwargs則是打包成一個(gè)字典格式,類似的功能在這篇博客中有所介紹。

第三次嘗試

上面的問題,在StackOverFlow上有一個(gè)類似的情況,有一個(gè)回答解決了這個(gè)問題,解決方案是,用PyObject_CallFunctionObjArgs來替代PyObject_CallObject去實(shí)現(xiàn)函數(shù)調(diào)用命令,相關(guān)代碼如下:

//cp.cpp

#includePython.h

#includeiostream

usingnamespacestd;

intmain(intargc,char*argv[])

Py_Initialize();

if(!Py_IsInitialized())

cout"Initializefailed!"endl;

return0;

PyObject*pModule=NULL;

PyObject*pFunc;

PyRun_SimpleString("importsys");

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

pModule=PyImport_ImportModule("pysplit");

if(pModule==NULL)

cout"ModuleNotFound!"endl;

pFunc=PyObject_GetAttrString(pModule,"sp");

PyObject*args=Py_BuildValue("s","TestStringHelloEveryOne!");

PyObject*pRet=PyObject_CallFunctionObjArgs(pFunc,args,NULL);

intsize=PyList_Size(p

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論