C語(yǔ)言中程序如何調(diào)用Python腳本
有時(shí)候在寫C語(yǔ)言程序的時(shí)候又想利用一下python強(qiáng)大的模塊,于是C與python的混合編程便應(yīng)運(yùn)而生。
下面簡(jiǎn)單說(shuō)說(shuō)在C語(yǔ)言編譯環(huán)境中調(diào)用python腳本文件的基礎(chǔ)應(yīng)用。
一、環(huán)境配置
以vs2017為例。
0x00 平臺(tái)
首先你要知道你電腦上安裝的python環(huán)境是64位還是32位,vs的編譯平臺(tái)需要與python環(huán)境一致。
比如我的python環(huán)境是64位,vs工程就要配置成x64。
右鍵點(diǎn)擊你的解決方案,點(diǎn)擊屬性,
0x01 添加 包含目錄 和 庫(kù)目錄
在屬性窗口雙擊“VC++ Directories”(VC++目錄),把在Include Directories (包含目錄)和 Library Directories(庫(kù)目錄)下添加python安裝路徑下的include和ibs文件夾的路徑。
0x02 添加依賴項(xiàng)
在添加之前一定要先確保自己安裝了python的debug版本,詳見(jiàn)我的另一篇博客【VS2017】“LNK1104 cannot open file ‘python39_d.lib‘
雙擊“l(fā)inker”(鏈接器)下的“Input”,添加python39_d.lib這個(gè)依賴項(xiàng)
點(diǎn)擊確定則配置完成。
這樣在寫程序的時(shí)候添加Python.h頭文件就不會(huì)報(bào)錯(cuò),python39_d.lib里的API函數(shù)也就可以正常使用了。
二、案例
主要流程就是:
- 初始化python
- 導(dǎo)入py腳本(模塊)
- 獲取模塊里的函數(shù)
- 必要的C語(yǔ)言數(shù)據(jù)類型轉(zhuǎn)python的數(shù)據(jù)類型(傳參前)
- 調(diào)用函數(shù)
- 釋放python
#include<stdio.h> #include <Python.h> int main() { PyObject *pName, *pModule, *pDict, *pFunc; PyObject *pArgs, *pValue; //待傳參數(shù) int time[6]={1,2,3,4,5,6}; //初始化python Py_Initialize(); // 檢查初始化是否成功 if (!Py_IsInitialized()) { printf("初始化失敗\n"); Py_Finalize(); } //設(shè)置python模塊,搜尋位置,文件放在.c文件一起 PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('./')"); //獲取python文件名,導(dǎo)入模塊(我這里的py文件是graph.py) pModule = PyImport_ImportModule("graph"); if (!pModule) { printf("py文件導(dǎo)入失敗\n"); Py_Finalize(); } else { //直接獲取模塊中的函數(shù) pFunc = PyObject_GetAttrString(pModule, "create_graph"); //驗(yàn)證函數(shù)是否獲取成功 if (!pFunc) { printf("函數(shù)導(dǎo)入失敗\n"); Py_Finalize(); } //將c/c++類型數(shù)據(jù)轉(zhuǎn)換為python類型,利用元組傳遞 pArgs = PyTuple_New(6); pValue = PyLong_FromLong(time[0]); PyTuple_SetItem(pArgs, 0, pValue); pValue = PyLong_FromLong(time[1]); PyTuple_SetItem(pArgs, 1, pValue); pValue = PyLong_FromLong(time[2]); PyTuple_SetItem(pArgs, 2, pValue); pValue = PyLong_FromLong(time[3]); PyTuple_SetItem(pArgs, 3, pValue); pValue = PyLong_FromLong(time[4]); PyTuple_SetItem(pArgs, 4, pValue); pValue = PyLong_FromLong(time[5]); PyTuple_SetItem(pArgs, 5, pValue); //調(diào)用直接獲得的函數(shù),并傳遞參數(shù) pValue = PyObject_CallObject(pFunc, pArgs); //釋放python Py_Finalize(); printf("success"); return 0; } }
順便給出我的graph.py的腳本,這是一個(gè)以參數(shù)的數(shù)值生成對(duì)應(yīng)的excel文件的腳本,這兩個(gè)源代碼是根據(jù)我的另一篇關(guān)于排序算法的博文改的案例。
# -*- coding:utf-8 -*- import xlsxwriter def create_graph(a,b,c,d,e,f): # 創(chuàng)建一個(gè)excel workbook = xlsxwriter.Workbook("排序算法比較結(jié)果.xlsx") # 創(chuàng)建一個(gè)sheet worksheet = workbook.add_worksheet() # worksheet = workbook.add_worksheet("bug_analysis") # 自定義樣式,加粗 bold = workbook.add_format({'bold': 1}) # --------1、準(zhǔn)備數(shù)據(jù)并寫入excel--------------- # 向excel中寫入數(shù)據(jù),建立圖標(biāo)時(shí)要用到 headings = ["排序方法", "排序時(shí)間"] data = [["簡(jiǎn)單選擇排序", "直接插入排序", "冒泡排序", "快速排序", "兩路合并排序", "堆排序"],[a,b,c,d,e,f]] # 寫入表頭 worksheet.write_row('A1', headings, bold) # 寫入數(shù)據(jù) worksheet.write_column('A2', data[0]) worksheet.write_column('B2', data[1]) # --------2、生成圖表并插入到excel--------------- # 創(chuàng)建一個(gè)柱狀圖(column chart) chart_col = workbook.add_chart({'type': 'column'}) # 配置第一個(gè)系列數(shù)據(jù) chart_col.add_series({'name': '=Sheet1!$B$1','categories': '=Sheet1!$A$2:$A$7','values': '=Sheet1!$B$2:$B$7','line': {'color': 'red'},}) # 這里的sheet1是默認(rèn)的值,因?yàn)槲覀冊(cè)谛陆╯heet時(shí)沒(méi)有指定sheet名 # 如果我們新建sheet時(shí)設(shè)置了sheet名,這里就要設(shè)置成相應(yīng)的值 # 設(shè)置圖表的title 和 x,y軸信息 chart_col.set_title({'name': "排序算法結(jié)果"}) chart_col.set_x_axis({'name': "排序方法"}) chart_col.set_y_axis({'name': "花費(fèi)時(shí)間(ms)"}) # 設(shè)置圖表的風(fēng)格 chart_col.set_style(1) # 把圖表插入到worksheet以及偏移 worksheet.insert_chart('A10', chart_col, {'x_offset': 25, 'y_offset': 10}) workbook.close() return 0 if __name__=="__main__": create_graph(10, 40, 50, 20, 10, 50)
三、常用API
1、運(yùn)行Python指令
PyRun_SimpleString("print(os.getcwd(),a)"); pyext.eval(R"(a+='qwer')");
2、加載Python模塊
PyObject * pModule =PyImport_ImportModule("tp"); //test:Python文件名,若腳本有錯(cuò)則返回空 PyRun_SimpleString("import os");
3、給Python的變量賦值
對(duì)于數(shù)值,使用Py_BuildValue:
Py_BuildValue("") None Py_BuildValue("i", 123) 123 Py_BuildValue("iii", 123, 456, 789) (123, 456, 789) Py_BuildValue("s", "hello") 'hello' Py_BuildValue("ss", "hello", "world") ('hello', 'world') Py_BuildValue("s#", "hello", 4) 'hell' Py_BuildValue("()") () Py_BuildValue("(i)", 123) (123,) Py_BuildValue("(ii)", 123, 456) (123, 456) Py_BuildValue("(i,i)", 123, 456) (123, 456) Py_BuildValue("[i,i]", 123, 456) [123, 456] Py_BuildValue("{s:i,s:i}", "abc", 123, "def", 456) {'abc': 123, 'def': 456}
對(duì)于其他數(shù)據(jù)結(jié)構(gòu),使用相應(yīng)的函數(shù)設(shè)置,例如:
PyObject *pArgs = PyTuple_New(1); PyObject *pDict = PyDict_New(); //創(chuàng)建字典類型變量 PyDict_SetItemString(pDict, "Name", Py_BuildValue("s", "YQC")); //往字典類型變量中填充數(shù)據(jù) PyDict_SetItemString(pDict, "Age", Py_BuildValue("i", 25)); //往字典類型變量中填充數(shù)據(jù) PyTuple_SetItem(pArgs, 0, pDict);//0---序號(hào) 將字典類型變量添加到參數(shù)元組中
構(gòu)造好對(duì)象以后,通過(guò)PyObject_SetAttrString來(lái)設(shè)置進(jìn)入Python中:
PyObject *ps=PyUnicode_DecodeUTF8(val,strlen(val),"ignore"); //構(gòu)造了一個(gè)對(duì)象 PyObject_SetAttrString(p_main_Module,key,ps); //設(shè)置
4、獲取Python變量的值
首先取得變量的指針,然后通過(guò)PyArg_Parse解析
pModule =PyImport_ImportModule("__main__"); pReturn = PyObject_GetAttrString(pModule, "a"); //可以獲得全局變量 int size = PyDict_Size(pReturn); PyObject *pNewAge = PyDict_GetItemString(pReturn, "Age"); int newAge; PyArg_Parse(pNewAge, "i", &newAge);
對(duì)于元組的解析:
PyObject * pfun=PyObject_GetAttrString(pModule, "testdict"); //testdict:Python文件中的函數(shù)名 PyObject *pReturn = PyEval_CallObject(pfun, pArgs); //調(diào)用函數(shù)
5、調(diào)用Python函數(shù)
PyObject * pfun=PyObject_GetAttrString(pModule, "testdict"); //testdict:Python文件中的函數(shù)名 PyObject *pReturn = PyEval_CallObject(pfun, pArgs); //調(diào)用函數(shù)
6、設(shè)置函數(shù)讓Python調(diào)用
首先定義c函數(shù),然后聲明方法列表,然后聲明模塊,然后增加這個(gè)模塊,最后調(diào)用
static int numargs=1890; static PyObject* emb_numargs(PyObject *self, PyObject *args) //C函數(shù) { if(!PyArg_ParseTuple(args, ":numargs")) return NULL; return PyLong_FromLong(numargs); } static PyMethodDef EmbMethods[] = { //方法列表 {"numargs", emb_numargs, METH_VARARGS, "Return the number of arguments received by the process."}, {NULL, NULL, 0, NULL} }; static PyModuleDef EmbModule = { //模塊聲明 PyModuleDef_HEAD_INIT, "emb", NULL, -1, EmbMethods, NULL, NULL, NULL, NULL }; static PyObject* PyInit_emb(void) //模塊初始化函數(shù) { return PyModule_Create(&EmbModule); } //增加模塊: PyImport_AppendInittab("emb", &PyInit_emb); //增加一個(gè)模塊
到此這篇關(guān)于C語(yǔ)言中程序如何調(diào)用Python腳本的文章就介紹到這了,更多相關(guān)C語(yǔ)言調(diào)用Python腳本內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
windows下安裝QT及visual studio 2017搭建開(kāi)發(fā)環(huán)境
這篇文章主要介紹了windows下安裝QT及visual studio 2017搭建開(kāi)發(fā)環(huán)境,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03深入剖析設(shè)計(jì)模式中的組合模式應(yīng)用及在C++中的實(shí)現(xiàn)
這篇文章主要介紹了設(shè)計(jì)模式中的組合模式應(yīng)用及在C++中的實(shí)現(xiàn),組合模式可以清晰地反映出遞歸構(gòu)建樹(shù)狀的組合結(jié)構(gòu),需要的朋友可以參考下2016-03-03詳解C++編程中的條件判斷語(yǔ)句if-else與switch的用法
這篇文章主要介紹了C++編程中的條件判斷語(yǔ)句if-else與switch的用法,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-01-01使用VS2019編譯CEF2623項(xiàng)目的libcef_dll_wrapper.lib的方法
這篇文章主要介紹了使用VS2019編譯CEF2623項(xiàng)目的libcef_dll_wrapper.lib的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04VS2022實(shí)現(xiàn)VC++打包生成安裝文件圖文詳細(xì)歷程
本文主要介紹了VS2022實(shí)現(xiàn)VC++打包生成安裝文件圖文詳細(xì)歷程,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02