欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何在C++中調(diào)用Python

 更新時間:2021年05月21日 16:50:45   作者:DECHIN  
雖然現(xiàn)在Python編程語言十分的火爆,但是實際上非要用一門語言去完成所有的任務(wù),并不是說不可以,而是不合適。在一些特定的、對于性能要求比較高的場景,還是需要用到傳統(tǒng)的C++來進(jìn)行編程的。本文將用C++的代碼去調(diào)用Python函數(shù)中實現(xiàn)的一些功能

Python的安裝

為了使用Python.h這個擴(kuò)展項,我們需要安裝一個python*-dev而不是python*,這兩者略有區(qū)別,下面的案例展示的是在Ubuntu20.04下安裝python3.9-dev的方法:

dechin@ubuntu2004:~/projects/gitlab/dechin/$ sudo apt install python3.9-dev
正在讀取軟件包列表... 完成
正在分析軟件包的依賴關(guān)系樹       
正在讀取狀態(tài)信息... 完成       
下列軟件包是自動安裝的并且現(xiàn)在不需要了:
  chromium-codecs-ffmpeg-extra gstreamer1.0-vaapi
  libgstreamer-plugins-bad1.0-0 linux-headers-5.8.0-43-generic
  linux-hwe-5.8-headers-5.8.0-43 linux-image-5.8.0-43-generic
  linux-modules-5.8.0-43-generic linux-modules-extra-5.8.0-43-generic
使用'sudo apt autoremove'來卸載它(它們)。
將會同時安裝下列軟件:
  libexpat1-dev libpython3.9 libpython3.9-dev zlib1g-dev
下列【新】軟件包將被安裝:
  libexpat1-dev libpython3.9 libpython3.9-dev python3.9-dev zlib1g-dev
升級了 0 個軟件包,新安裝了 5 個軟件包,要卸載 0 個軟件包,有 30 個軟件包未被升級。
需要下載 6,613 kB 的歸檔。
解壓縮后會消耗 28.7 MB 的額外空間。
您希望繼續(xù)執(zhí)行嗎? [Y/n] Y
獲取:1 http://repo.huaweicloud.com/ubuntu focal/main amd64 libexpat1-dev amd64 2.2.9-1build1 [116 kB]
獲取:2 http://repo.huaweicloud.com/ubuntu focal-updates/universe amd64 libpython3.9 amd64 3.9.0-5~20.04 [1,710 kB]
獲取:3 http://repo.huaweicloud.com/ubuntu focal-updates/universe amd64 libpython3.9-dev amd64 3.9.0-5~20.04 [4,119 kB]
獲取:4 http://repo.huaweicloud.com/ubuntu focal-updates/main amd64 zlib1g-dev amd64 1:1.2.11.dfsg-2ubuntu1.2 [155 kB]
獲取:5 http://repo.huaweicloud.com/ubuntu focal-updates/universe amd64 python3.9-dev amd64 3.9.0-5~20.04 [512 kB]
已下載 6,613 kB,耗時 4秒 (1,594 kB/s)
正在選中未選擇的軟件包 libexpat1-dev:amd64。
(正在讀取數(shù)據(jù)庫 ... 系統(tǒng)當(dāng)前共安裝有 269544 個文件和目錄。)
準(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,是可以看到一個python專屬的命令行界面的,可以通過exit()退出。但是我們這里側(cè)重的是跟C++的配合工作,因此我們更加關(guān)注lib和include目錄下是否有生成相關(guān)的目錄,可以執(zhí)行如下指令進(jìn)行查看:

dechin@ubuntu2004:~/projects/gitlab/dechin/$ ll /usr/lib/ | grep python
drwxr-xr-x  26 root root   20480 5月   7 16:27 python2.7/
drwxr-xr-x   3 root root    4096 2月  10 02:47 python3/
drwxr-xr-x  30 root root   20480 5月   7 16:30 python3.8/
drwxr-xr-x  31 root root   12288 5月  20 16:31 python3.9/

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

dechin@ubuntu2004:~/projects/gitlab/dechin/$ ll /usr/include/ | grep python
drwxr-xr-x  2 root root   4096 5月   7 16:31 python3.8/
drwxr-xr-x  4 root root   4096 5月  20 16:31 python3.9/

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

VS Code配置

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

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "gnu17",
            "cppStandard": "c++11",
            "intelliSenseMode": "linux-gcc-x64"
        }
    ],
    "version": 4
}

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

{
    "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
}

添加后,include <Python.h>就不會顯示報錯了。

Hello World測試

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

// cp.cpp
#include <Python.h>
int main(int argc, char *argv[]) {
  Py_Initialize();
  PyRun_SimpleString("print('hello world')\n");
  Py_Finalize();
  return 0;
}

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

dechin@ubuntu2004:~/projects/gitlab/dechin/$ g++ -o cpy cp.cpp -lm -std=c++11 -I/usr/include/python3.9/ -lpython3.9
dechin@ubuntu2004:~/projects/gitlab/dechin/$ ll
總用量 4697388
drwxrwxr-x 2 dechin dechin       4096 5月  20 17:10 ./
drwxrwxr-x 8 dechin dechin       4096 5月  19 15:32 ../
-rw-rw-r-- 1 dechin dechin        152 5月  20 17:04 cp.cpp
-rwxrwxr-x 1 dechin dechin      16776 5月  20 17:10 cpy*

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

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

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

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

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

第一次嘗試

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

// cp.cpp
#include <Python.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
  Py_Initialize();
  if (!Py_IsInitialized())
	{
		cout << "Initialize failed!" << endl;
		return 0;
	}
  PyObject* pModule = NULL;
  PyObject* pFunc;
  PyRun_SimpleString("import os");
  PyRun_SimpleString("os.system('pwd')");
  pModule = PyImport_ImportModule("pysplit");
  if (pModule == NULL)
	{
		cout << "Module Not Found!" << endl;
	}
  // pFunc = PyObject_GetAttrString(pModule, "sp");
  // PyObject* args = Py_BuildValue("s", "Test String Hello Every One !");
  // PyObject* pRet = PyObject_CallObject(pFunc, args);
  string cList[10];
  // PyArg_Parse(pRet, "[items]", &cList);
  cout << "res:" << cList << endl;
  Py_Finalize();
  return 0;
}

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

# pysplit.py

def sp(string):
    return string.split()

這是一個非常簡單的函數(shù),但是我們在調(diào)用的時候就直接返回了一個錯誤:

dechin@ubuntu2004:~/projects/gitlab/dechin/$ g++ -o cpy cp.cpp -lm -std=c++11 -I/usr/include/python3.9/ -lpython3.9 && ./cpy
['pysplit.py', 'cpy', 'cp.cpp']
Module Not Found!
res:0x7ffc622ae900

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

第二次嘗試

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

// cp.cpp
#include <Python.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
  Py_Initialize();
  if (!Py_IsInitialized())
	{
		cout << "Initialize failed!" << endl;
		return 0;
	}
  PyObject* pModule = NULL;
  PyObject* pFunc;
  PyRun_SimpleString("import sys");
  PyRun_SimpleString("sys.path.append('./')");
  pModule = PyImport_ImportModule("pysplit");
  if (pModule == NULL)
	{
		cout << "Module Not Found!" << endl;
	}
  pFunc = PyObject_GetAttrString(pModule, "sp");
  PyObject* args = Py_BuildValue("s", "Test String Hello Every One !");
  PyObject* pRet = PyObject_CallObject(pFunc, args);
  string cList[10];
  // PyArg_Parse(pRet, "[items]", &cList);
  cout << "res:" << cList << endl;
  Py_Finalize();
  return 0;
}

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

第三次嘗試

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

// cp.cpp
#include <Python.h>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
  Py_Initialize();
  if (!Py_IsInitialized())
	{
		cout << "Initialize failed!" << endl;
		return 0;
	}
  PyObject* pModule = NULL;
  PyObject* pFunc;
  PyRun_SimpleString("import sys");
  PyRun_SimpleString("sys.path.append('./')");
  pModule = PyImport_ImportModule("pysplit");
  if (pModule == NULL)
	{
		cout << "Module Not Found!" << endl;
	}
  pFunc = PyObject_GetAttrString(pModule, "sp");
  PyObject* args = Py_BuildValue("s", "Test String Hello Every One !");
  PyObject* pRet = PyObject_CallFunctionObjArgs(pFunc, args, NULL);
  int size = PyList_Size(pRet);
  cout << "List size is: " << size << endl;
  for(int i=0;i<size;i++)
  {
    PyObject* cRet = PyList_GET_ITEM(pRet, i);
    char* s;
    PyArg_Parse(cRet, "s", &s);
    cout << "The " << i << "th term is: " << s << endl;
  }
  Py_Finalize();
  return 0;
}

最后,因為從Python中獲取的是一個List格式的數(shù)據(jù),因此我們首先需要用PyList_GET_ITEM去逐項提取,然后用PyArg_Parse將提取出來的元素保存到一個C++的char字符串中,執(zhí)行結(jié)果如下:

dechin@ubuntu2004:~/projects/gitlab/dechin/$ g++ -o cpy cp.cpp -lm -std=c++11 -I/usr/include/python3.9/ -lpython3.9 && ./cpy
List size is: 6
The 0th term is: Test
The 1th term is: String
The 2th term is: Hello
The 3th term is: Every
The 4th term is: One
The 5th term is: !

Yes!終于成功了!

總結(jié)概要

本文介紹了一個在C++內(nèi)部調(diào)用Python中封裝的函數(shù)或者接口的方法,從環(huán)境配置到具體示例都有講解,并且在其中包含有不少的坑點(diǎn),需要一步一步去踩。不同的編程語言具有不同的優(yōu)勢,Python輪子眾多而語法簡單,上手容易,但是性能比較首先,C++的最明顯優(yōu)勢就是在于其性能的天然優(yōu)越性。但是我們不需要對哪一種編程語言有所偏倚,都有所掌握,并且能夠有所互通,利用好各自的優(yōu)勢,才能夠發(fā)揮最大的價值。

以上就是如何在C++中調(diào)用Python的詳細(xì)內(nèi)容,更多關(guān)于C++ 調(diào)用Python的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Django卸載之后重新安裝的方法

    Django卸載之后重新安裝的方法

    如果你打算從過去的一個版本升級Django, 你需要先刪除老版本的Django之后,再安裝新的版本。下面這篇文章主要給大家介紹了在Django卸載之后重新安裝的方法,文中給出了詳細(xì)的步驟,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-03-03
  • python+pyqt5實現(xiàn)圖片批量縮放工具

    python+pyqt5實現(xiàn)圖片批量縮放工具

    這篇文章主要為大家詳細(xì)介紹了Python+pyqt5實現(xiàn)圖片批量縮放工具,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-03-03
  • 使用python進(jìn)行文本預(yù)處理和提取特征的實例

    使用python進(jìn)行文本預(yù)處理和提取特征的實例

    今天小編就為大家分享一篇使用python進(jìn)行文本預(yù)處理和提取特征的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • python request 模塊詳細(xì)介紹

    python request 模塊詳細(xì)介紹

    這篇文章主要介紹了python request 模塊詳細(xì)介紹,幫助大家利用request 模塊學(xué)習(xí)爬蟲,感興趣的朋友可以了解下
    2020-11-11
  • Python如何實現(xiàn)Excel的最合適列寬(openpyxl)

    Python如何實現(xiàn)Excel的最合適列寬(openpyxl)

    這篇文章主要介紹了Python如何實現(xiàn)Excel的最合適列寬(openpyxl),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 新年快樂! python實現(xiàn)絢爛的煙花綻放效果

    新年快樂! python實現(xiàn)絢爛的煙花綻放效果

    這篇文章主要為大家詳細(xì)介紹了python利用可視化技巧實現(xiàn)煙花綻放效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • Python簡單刪除目錄下文件以及文件夾的方法

    Python簡單刪除目錄下文件以及文件夾的方法

    這篇文章主要介紹了Python簡單刪除目錄下文件以及文件夾的方法,涉及Python使用shutil模塊操作文件的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • python識別驗證碼圖片實例詳解

    python識別驗證碼圖片實例詳解

    這篇文章主要介紹了python識別驗證碼圖片實例詳解,需要的朋友可以參考下
    2020-02-02
  • 解讀Numpy中的排序(sort,argsort)

    解讀Numpy中的排序(sort,argsort)

    這篇文章主要介紹了關(guān)于Numpy中的排序(sort,argsort),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Python利用ElementTree模塊處理XML的方法詳解

    Python利用ElementTree模塊處理XML的方法詳解

    ElementTree是python的XML處理模塊,它提供了一個輕量級的對象模,下面這篇文章就來給大家介紹了關(guān)于Python利用ElementTree模塊處理XML的方法,文中通過示例代碼介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。
    2017-08-08

最新評論