使用C++呼叫Python程式碼的方法詳解
一、配置python環境問題
1.首先安裝Python(版本無所謂),安裝的時候選的新增python路徑到環境變數中
安裝之後的資料夾如下所示:
2.在VS中配置環境和庫 右擊專案->屬性->VC++目錄
1)包含目錄:
Python安裝路徑/include
2)庫目錄:
Python安裝路徑/libs
右擊專案->屬性->聯結器->輸入->附加依賴庫
debug下:
python安裝目錄/libs/python37_d.lib
release下:
python安裝目錄/libs/python37.lib
注意
1、debug配置的時候可能沒有python37_d.lib,那就把python37.lib複製一個,然後重新命名為python37_d.lib就可以啦
2、如果一直報錯,但是包含標頭檔案等都沒有問題,那麼你需要看一下你的python是32位還是64位的。然後根據python的環境去配置vs的環境。
二、C++呼叫python函式並輸出返回值
首先可能有個坑!一定要保證這個python函式所在的檔案能夠正常執行!然後把python程式碼放到和C++程式碼同一目錄下。
1、定義Python函式
#!python3 # -*- coding:utf-8 -*- import base64 import hmac from hashlib import sha1 def hash_hmac(code,key): #sha1加密簽名演算法 hmac_code = hmac.new(key.encode(),code.encode(),sha1).digest() return base64.b64encode(hmac_code).decode()
2、編寫C++程式碼
#include <iostream> #include<python.h> using namespace std; int main() { Py_Initialize();//使用python之前,要呼叫Py_Initialize();這個函式進行初始化 if (!Py_IsInitialized()) { printf("初始化失敗!"); return 0; } PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('./')");//這一步很重要,修改Python路徑 PyObject* pModule = NULL;//宣告變數 PyObject* pFunc = NULL;// 宣告變數 pModule = PyImport_ImportModule("hash_hmac");//這裡是要呼叫的檔名hash_hmac.py if (pModule == NULL) { cout << "沒找到" << endl; } pFunc = PyObject_GetAttrString(pModule,"hash_hmac");//這裡是要呼叫的函式名 //兩個字串引數 PyObject* pParams = Py_BuildValue("(ss)","/oss/upload?bucket=test&filekey=test/image/3b/3ba9d94cab2f8868823d71c4445e125a.png\n","q4mJAS777BUbbdVpEqh2XRcZZqNyDweU4GRnM690"); char* result; PyObject* pRet = PyObject_CallObject(pFunc,pParams);//呼叫函式 int res = 0; PyArg_Parse(pRet,"s",&result);//轉換返回型別 cout << "res:" << result << endl;//輸出結果 Py_Finalize();//呼叫Py_Finalize,這個根Py_Initialize相對應的。 return 0; }
3、解釋部分C++程式碼
PyObject* pParams = Py_BuildValue("(ss)","q4mJAS777BUbbdVpEqh2XRcZZqNyDweU4GRnM690");
在這裡我輸入了兩個字串型別的引數,Py_BuildValue()函式的作用和PyArg_ParseTuple()的作用相反,它將C型別的資料結構轉換成Python物件。
該函式可以和PyArg_ParseTuple()函式一樣識別一系列的格式串,但是輸入引數只能是值,而不能是指標。
它返回一個Python物件和PyArg_ParseTuple()不同的一點是PyArg_ParseTuple()函式它的第一個引數為元組,Py_BuildValue()則不一定會生成一個元組。它生成一個元組僅僅當格式串包含兩個或者多個格式單元,如果格式串為空,返回NONE。
在下面的描述中,括號中的項是格式單元返回的Python物件型別,方括號中的項為傳遞的C的值的型別。
“s” (string) [char *] :將C字串轉換成Python物件,如果C字串為空,返回NONE。
“s#” (string) [char *,int] :將C字串和它的長度轉換成Python物件,如果C字串為空指標,長度忽略,返回NONE。
“z” (string or None) [char *] :作用同”s”。
“z#” (string or None) [char *,int] :作用同”s#”。
“i” (integer) [int] :將一個C型別的int轉換成Python int物件。
“b” (integer) [char] :作用同”i”。
“h” (integer) [short int] :作用同”i”。
“l” (integer) [long int] :將C型別的long轉換成Pyhon中的int物件。
“c” (string of length 1) [char] :將C型別的char轉換成長度為1的Python字串物件。
“d” (float) [double] :將C型別的double轉換成python中的浮點型物件。
“f” (float) [float] :作用同”d”。
“O&” (object) [converter,anything] :將任何資料型別通過轉換函式轉換成Python物件,這些資料作為轉換函式的引數被呼叫並且返回一個新的Python物件,如果發生錯誤返回NULL。
“(items)” (tuple) [matching-items] :將一系列的C值轉換成Python元組。
“[items]” (list) [matching-items] :將一系列的C值轉換成Python列表。
“{items}” (dictionary) [matching-items] :將一系類的C值轉換成Python的字典,每一對連續的C值將轉換成一個鍵值對。
例如:
Py_BuildValue(“”) None
Py_BuildValue(“i”,123) 123
Py_BuildValue(“iii”,123,456,789) (123,789)
Py_BuildValue(“s”,“hello”) ‘hello'
Py_BuildValue(“ss”,“hello”,“world”) (‘hello',‘world')
Py_BuildValue(“s#”,4) ‘hell'
Py_BuildValue(“()”) ()
Py_BuildValue(“(i)”,123) (123,)
Py_BuildValue(“(ii)”,456) (123,456)
Py_BuildValue(“(i,i)”,456)
Py_BuildValue(“[i,i]”,456) [123,456] Py_BuildValue(“{s:i,s:i}”,“abc”,“def”,456) {‘abc': 123,‘def': 456}
Py_BuildValue(“((ii)(ii)) (ii)”,1,2,3,4,5,6) (((1,2),(3,4)),(5,6))
3、執行C++程式
與Python程式碼的預期相同。
三、Python程式碼處理
在釋出軟體的時候,通常我們都不希望程式碼可以直接被別人看到。
以上的Debug目錄中的exe要想能夠單獨執行,必須把python指令碼拷過去。為了不讓別人能直接看到我的程式碼,我拷過去的是生成的.pyc檔案,實現了一個簡單的python程式碼的加密。不過據說可以反編譯,但是對我來說已經夠了。
四、.py和.pyc的區別
原來Python的程式中,是把原始程式程式碼放在.py檔案裡,而Python會在執行.py檔案的時候。將.py形式的程式編譯成中間式檔案(byte-compiled)的.pyc檔案,這麼做的目的就是為了加快下次執行檔案的速度。
所以,在我們執行python檔案的時候,就會自動首先檢視是否具有.pyc檔案,如果有的話,而且.py檔案的修改時間和.pyc的修改時間一樣,就會讀取.pyc檔案,否則,Python就會讀原來的.py檔案。
其實並不是所有的.py檔案在與執行的時候都會產生.pyc檔案,只有在import相應的.py檔案的時候,才會生成相應的.pyc檔案。
五、使用.py生成.pyc
在命令列下使用下列命令即可:
python -m py_compile test.py#單檔案 python -m py_compile /root/src/{file1,file2}.py#多檔案
總結
以上所述是小編給大家介紹的使用C++呼叫Python程式碼的方法詳解,希望對大家有所幫助!