C++調用Python處理vector

前言

C++和Python都是當前最流行的語言之一,其強大的功能毋庸置疑,它們分別在不同甚至相同的領域發揮着至關重要的作用。C++是底層開發中起着中流砥柱的作用,屹立多年依然勢頭強勁不露頹勢。而Python在最近大熱的數據挖掘和人工智能領域獨領風騷。而且Python爲數極其衆多的庫支持幾乎可以滿足各個領域的開發者的需求。

雖然他們都是非常強大的工具,但是在處理特定任務的時候,有時候會存在着方便與否的問題。比如說在算法實現上可能我更喜歡用C++,但是算法最後產生的數據卻想交給Python來處理,畢竟Python在數據處理方面用起來更加順手也更加簡單。本文中我們就來看一下如何把C++算法得到的數據vector<float>交給Python然後用Excel畫出來。

環境配置

首先需要配置一下環境,我這裏用的分別是:

Visual Studio 2017

Anaconda 2 (64位)

正如在Visual Studio中配置其他庫(比如OpenCV)一樣,我們需要在Visual Studio中添加三個東西

包含目錄——include文件夾

庫目錄——包含.lib文件的文件夾

附加依賴項——.lib文件

按照上面的順序,我們需要分別將Python安裝文件下的inlcude文件夾、libs文件夾和libs文件夾下的python27.lib添加到VS工程屬性的包含目錄、庫目錄和附加依賴項中去。如下圖:

這裏有兩點需要注意:

  • 要把模式設置爲Release而不是Debug,否則要把python27.lib改名爲python27_d.lib

  • 要根據安裝的Python的位數來選擇平臺爲數,比如這裏是64位

C++調用Python

在上代碼之前還是說一下C++調用Python的一些慣例比較好:

  1. 添加頭文件Python.h,確保文件夾include加入到了包含目錄才能調用成功

  2. 調用的Python代碼都需要包含在兩行代碼中間,即如下形式:

Py_Initialize();  //首。初始化Python解釋器

//這裏是一堆其他代碼

Py_Initialize();  //尾。結束Python的工作。

  1. 跟Python相關的東西一般聲明爲PyObject指針的形式,比如一會見到的如下聲明:

PyObject * pModule = NULL; //Python模塊

PyObject * pFunc = NULL;   //Python函數

PyObject * pArg = NULL;    //函數接受的參數

  1. 用下面三行代碼來完成導入模塊、引入函數、構建參數的工作,都是”聞名如見面“類型的函數:

pModule = PyImport_ImportModule("test"); //導入模塊

pFunc = PyObject_GetAttrString(pModule, "write_to_xlsx"); //引入操作Excel的函數

pArg = Py_BuildValue("O,O", tuple1, tuple2); //把C++類型轉換爲Python類型

  1. 最後用一句,把參數傳給調用函數並實際運行:

PyEval_CallObject(pFunc, pArg);

實際上到這裏就已經把幾乎所有能用到的都說個差不多了,在具體說一下C++類型轉換爲Python類型之前,還是先看一下完整的代碼吧。

Show me your code.

vector轉爲tuple

其他的諸如引入模塊、函數之類的是沒啥難度的,只需要換個參數而已。這裏實際具有技術含量的就是vector對於轉化爲tuple這一部分了。

其中最主要的一個函數是PyObject *Py_BuildValue(char *format, ...);,此函數作用就是把後面的參數轉換成第一個參數format指定的形式,最終返回一個Python對象。官方給出的例子有這些:

但是當我想要把兩個vector傳給轉換成兩個tuple的時候,上面給出的N種形式都顯得力不從心了。我們希望兩個vector傳遞給Python的時候轉換成了兩個tuple。但是最後的結果經常是變成了一個個的單個元素,就是不能把這些元素按照原來的vector分成兩個元組。經過苦讀文檔加上實驗,format參數是'O'的時候能夠滿足需求。但是需要我們先把vector轉成tuple才能格式化參數。

PyObject* tuple = PyTuple_New(data.size());

先通過PyTuple_New創建一個Python對象,然後利用PyTuple_SET_ITEM把vector的元素一個一個添加到tuple裏面去:

PyTuple_SET_ITEM(tuple, i, Py_BuildValue("f", data[i]));

這樣,參數就可以經過Py_BuildValue格式化之後傳給被調用的函數了。

調用的Python程序

在本文中被調用的Python程序不是我們關注的重點,所以Python代碼直接放在這裏不做過多的解釋。大概意思就是利用Openpyxl,把接收的數據寫入Excel,然後畫出柱狀圖。也許以後會放出這方面的內容。現在就只是知道調用的代碼長什麼樣就行。以下是test.py的內容:

最後的效果

可以看到,傳遞給Python的參數已經成功的寫入Excel並畫出了直方圖。值得注意的一點是,VS運行程序的時候Excel要關閉,不然會發生寫入數據失敗。

發佈了48 篇原創文章 · 獲贊 43 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章