C++調(diào)用python(執(zhí)行py文件)的全過(guò)程
1、首先要配好vs開(kāi)發(fā)工程
注意版本;我這使用32位的python那么我vs工程這邊也選擇32位的編譯環(huán)境去配置
注意點(diǎn);需要將python安裝目錄的一些文件拷過(guò)來(lái)作為vs工程使用。
2、C++調(diào)用Python結(jié)果
py代碼
這里引用了cdll庫(kù)也需要放置到運(yùn)行目錄,py文件也是需要放置到運(yùn)行目錄(也就是exe生成所在目錄)
import os import time from ctypes import * def testDLL(): pDll = CDLL("./pythonTestCDll.dll") pstr = create_string_buffer(1024, '\0') # 創(chuàng)建字符串緩沖區(qū) # 對(duì)輸入輸出參數(shù)進(jìn)行聲明 GetAndSetString = pDll.GetAndSetString GetAndSetString.restype = c_char_p GetAndSetString.argtypes = [c_char_p] pchar = GetAndSetString(pstr) szbuffer = c_char_p(pchar) # 強(qiáng)制轉(zhuǎn)換為c_char_p類型,取其value值 print(pstr.value) print(szbuffer.value) def Start(): testDLL()
C++代碼
#include <iostream> #include "Python.h" using namespace std; void Hello(); void Add(); void Start(); void Hello1() { cout << "\n調(diào)用Test001.py中的Add函數(shù)..." << endl; } int main(int argc, char* argv[]) { /*cout << "調(diào)用Test001.py中的Hello函數(shù)..." << endl; Hello(); cout << "\n調(diào)用Test001.py中的Add函數(shù)..." << endl; Add();*/ cout << "調(diào)用testMultiprocessingDll.py中的Start函數(shù)..." << endl; Start(); getchar(); return 0; } void Start() { Py_Initialize();//調(diào)用Py_Initialize()進(jìn)行初始化 if (!Py_IsInitialized()) { printf("Python envirment initialized fale!"); return; } PyObject * pModule = NULL; PyObject * pFunc = NULL; PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('D:/code/pythonTestCDll/CdoPython/Release/DLLs')"); //PyRun_SimpleString("print(\"sdasd\")"); pModule = PyImport_ImportModule("testMultiprocessingDll");//調(diào)用的Python文件名 py文件放置exe同級(jí) if (pModule == NULL) { PyErr_Print(); cout << "PyImport_ImportModule Fail!" << endl; return; } pFunc = PyObject_GetAttrString(pModule, "__main__");//調(diào)用的函數(shù)名 PyEval_CallObject(pFunc, NULL);//調(diào)用函數(shù),NULL表示參數(shù)為空 Py_Finalize();//調(diào)用Py_Finalize,和Py_Initialize相對(duì)應(yīng)的. } void Hello() { Py_Initialize();//調(diào)用Py_Initialize()進(jìn)行初始化 if (!Py_IsInitialized()) { printf("Python envirment initialized fale!"); return ; } PyObject * pModule = NULL; PyObject * pFunc = NULL; PyRun_SimpleString("print(\"sdasd\")" ); pModule = PyImport_ImportModule("Test001");//調(diào)用的Python文件名 py文件放置exe同級(jí) if (pModule == NULL) { PyErr_Print(); cout << "PyImport_ImportModule Fail!" << endl; return; } pFunc = PyObject_GetAttrString(pModule, "Hello");//調(diào)用的函數(shù)名 PyEval_CallObject(pFunc, NULL);//調(diào)用函數(shù),NULL表示參數(shù)為空 Py_Finalize();//調(diào)用Py_Finalize,和Py_Initialize相對(duì)應(yīng)的. } //調(diào)用Add函數(shù),傳兩個(gè)int型參數(shù) void Add() { Py_Initialize(); PyObject * pModule = NULL; PyObject * pFunc = NULL; pModule = PyImport_ImportModule("Test001");//Test001:Python文件名 pFunc = PyObject_GetAttrString(pModule, "Add");//Add:Python文件中的函數(shù)名 //創(chuàng)建參數(shù): PyObject *pArgs = PyTuple_New(2);//函數(shù)調(diào)用的參數(shù)傳遞均是以元組的形式打包的,2表示參數(shù)個(gè)數(shù) PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 6));//0--序號(hào),i表示創(chuàng)建int型變量 PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 8));//1--序號(hào) //返回值 PyObject *pReturn = NULL; pReturn = PyEval_CallObject(pFunc, pArgs);//調(diào)用函數(shù) //將返回值轉(zhuǎn)換為int類型 int result; PyArg_Parse(pReturn, "i", &result);//i表示轉(zhuǎn)換成int型變量 cout << "6 + 8 = " << result << endl; Py_Finalize(); }
3、報(bào)錯(cuò):ValueError: source code string cannot contain null bytes
參考鏈接:
https://blog.csdn.net/LaoYuanPython/article/details/97623504
https://blog.csdn.net/zichen_ziqi/article/details/79068656
4、C++調(diào)用python文件中import時(shí)報(bào)錯(cuò)
參考鏈接://www.dbjr.com.cn/article/233313.htm
5、C++多線程調(diào)用Python多進(jìn)程multiprocessing時(shí)發(fā)現(xiàn)不支持
C++多線程調(diào)用Python多進(jìn)程
C++、Java等編程想提高效率,很容易想到的就是使用多線程,而在Python中,由于使用了GIL,使得多線程效率非但沒(méi)有將性能線性提升,反而可能會(huì)比單線程效率還低。在進(jìn)程間不需要怎么通信的時(shí)候,multiprocessing就很好用了。但是翻遍了C/Python API沒(méi)找到C語(yǔ)言調(diào)用Python多進(jìn)程的方法。而目前的項(xiàng)目卻恰好希望能用C++調(diào)用Python多進(jìn)程。嘗試了好多C/Python API都沒(méi)有一個(gè)穩(wěn)定可靠的方案,今天終于試出來(lái)了一種可行的方案!
該方案的前提是進(jìn)程間不需要通信!
方法很簡(jiǎn)單,使用linux的shell啟動(dòng)python進(jìn)程!
C++部分思路:
1. 使用c++創(chuàng)建多個(gè)線程,根據(jù)自己的邏輯寫好入口函數(shù)和輸入?yún)?shù)
2. 在線程入口函數(shù)中,將想要執(zhí)行的linux命令封裝成一個(gè)字符串如s=”python test.py a b c”,其中a,b,c是test.py的系統(tǒng)參數(shù),完成了C++向python的傳參,當(dāng)然只是一些簡(jiǎn)單的類型
3. 定義好python的控制臺(tái)上的輸出,使用popen()執(zhí)行s的命令并建立管道
4. 獲取控制臺(tái)的輸出,并按照已定義好的規(guī)則來(lái)判斷返回信息
5. 根據(jù)返回信息,執(zhí)行對(duì)應(yīng)的操作
Python部分思路:
基本不用修改,只是把普通的函數(shù)傳參改為獲取系統(tǒng)參數(shù),將函數(shù)返回值改為控制臺(tái)輸出,當(dāng)然返回值類型受限
該方案成功解決了C++多線程調(diào)用Python多進(jìn)程的問(wèn)題,提升了效率,缺點(diǎn)是進(jìn)程間不能通信,只能相互傳遞比較簡(jiǎn)單的參數(shù)!
總結(jié)
到此這篇關(guān)于C++調(diào)用python(執(zhí)行py文件)的文章就介紹到這了,更多相關(guān)C++調(diào)執(zhí)行py文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列(面試官的小結(jié))
這篇文章主要給大家介紹了關(guān)于C++用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的相關(guān)資料,這是來(lái)自一名面試官的小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05C語(yǔ)言中的浮點(diǎn)數(shù)據(jù)類型
這篇文章主要介紹了C語(yǔ)言中的浮點(diǎn)數(shù)據(jù)類型,文章會(huì)從處理帶小數(shù)的數(shù)值的相關(guān)資料開(kāi)始介紹,感興趣的小伙伴的可以參考下面 文章的具體內(nèi)容2021-10-10C語(yǔ)言進(jìn)階幾分鐘帶你理解大小端存儲(chǔ)模式
這篇文章主要為大家介紹了C語(yǔ)言進(jìn)階大小端模式的示例詳解,帶各位讀者朋友五分鐘腳踩大小端模式,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02OpenCV中的cv::Mat函數(shù)將數(shù)據(jù)寫入txt文件
這篇文章主要介紹了OpenCVcv::Mat中的數(shù)據(jù)按行列寫入txt文件中,需要的朋友可以參考下2018-05-05C語(yǔ)言程序設(shè)計(jì)第五版譚浩強(qiáng)課后答案(第二章答案)
這篇文章主要介紹了C語(yǔ)言程序設(shè)計(jì)第五版譚浩強(qiáng)課后答案(第二章答案),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2021-04-04C++實(shí)現(xiàn)LeetCode(94.二叉樹(shù)的中序遍歷)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(94.二叉樹(shù)的中序遍歷),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C語(yǔ)言學(xué)生成績(jī)管理系統(tǒng)小設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言學(xué)生成績(jī)管理系統(tǒng)小設(shè)計(jì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01