1. 程式人生 > >c++調用python系列(1): 結構體作為入參及返回結構體

c++調用python系列(1): 結構體作為入參及返回結構體

pac 格式 lob 打包成 def 程序 png 校驗 upload

最近在打算用python作測試用例以便對遊戲服務器進行功能測試以及壓力測試;

因為服務器是用c++寫的,采用的TCP協議,當前的架構是打算用python構造結構體,傳送給c++層進行socket發送給遊戲服務器,響應消息再交由python進行校驗;

技術分享

開始:

首先是c++調用python這一層需要打通;

幸運的是python自己有一套庫提供c/c++進行調用;

下面我貼代碼;用的vs2013,python用的2.7

 1 // python_c++.cpp : 定義控制臺應用程序的入口點。
 2 //
 3 
 4 #include "stdafx.h"
 5 #include <Python.h>
 6
#pragma comment(lib, "Ws2_32.lib") 7 8 int _tmain(int argc, _TCHAR* argv[]) 9 { 10 // 初始化Python 11 Py_Initialize(); 12 // 檢查初始化是否成功 13 if (!Py_IsInitialized()) { 14 return -1; 15 } 16 // 添加當前路徑 17 //把輸入的字符串作為Python代碼直接運行,返回0 18 //表示成功,-1表示有錯。大多時候錯誤都是因為字符串中有語法錯誤。
19 PyRun_SimpleString("import sys"); 20 int result = PyRun_SimpleString("print(‘----------import sys-------‘)"); 21 if (result!=-1){ 22 printf("test pyhon OK!\n\n"); 23 } 24 25 PyRun_SimpleString("sys.path.append(‘./‘)"); 26 27 // 載入名為pytest的腳本 28 PyObject *pName = PyBytes_FromString("
pytest"); 29 PyObject *pModule = PyImport_Import(pName); 30 if (!pModule) { 31 printf("can‘t find pytest.py"); 32 getchar(); 33 return -1; 34 } 35 36 PyObject *pDict = PyModule_GetDict(pModule); 37 if (!pDict) { 38 getchar(); 39 return -1; 40 } 41 42 //下面這段是查找函數test 並執行test 43 PyObject *pFunc = PyDict_GetItemString(pDict, "test2"); 44 if (!pFunc || !PyCallable_Check(pFunc)) { 45 printf("can‘t find function [test2]"); 46 getchar(); 47 return -1; 48 } 49 50 typedef struct header_ { 51 int buf1; 52 int buf2; 53 char buf3[11]; 54 int buf4; 55 }header; 56 57 //創建結構體 58 header input; 59 memset(&input,0,sizeof(input)); 60 input.buf1 = 1; 61 input.buf2 = 2; 62 input.buf4 = 3; 63 strcpy_s(input.buf3, "kjac"); 64 65 //打包成byte* 66 char * byInput = new char(sizeof(input)); 67 memcpy(byInput, &input, sizeof(input)); 68 69 //申請python入參 70 PyObject *pArgs = PyTuple_New(1); 71 //對python入參進行賦值; s代表char*格式, #代表傳入指定長度 72 PyTuple_SetItem(pArgs, 0, Py_BuildValue("s#", byInput, sizeof(input))); 73 74 //執行函數 75 PyObject *pResult = PyObject_CallObject(pFunc, pArgs); 76 77 char* pRsp; 78 //獲取返回值 79 PyArg_Parse(pResult, "s", &pRsp); 80 81 //轉成結構體 82 header* pstRsp = (header*)pRsp; 83 printf("\n-----------c++層接收py返回:buf1:%d,buf2:%d,buf3:%s,buf4:%d\n", 84 pstRsp->buf1, pstRsp->buf2, pstRsp->buf3, pstRsp->buf4); 85 86 //釋放 87 Py_DECREF(pName); 88 Py_DECREF(pArgs); 89 Py_DECREF(pModule); 90 91 // 關閉Python 92 Py_Finalize(); 93 getchar(); 94 return 0; 95 }

下面的是python代碼

 1 import struct
 2 
 3 def test(a):
 4     print("----------------------------python 1-----------------------")
 5     ret = struct.unpack(ii11si, a)
 6     print("----------------------------python deal-----------------------")
 7     print("--------------------python receive c++ struct:")
 8     print("begin unpack:")
 9     print("")
10     print(ret)
11     buf1 = ret[0] + 1
12     buf2 = ret[1] + 1
13     buf4 = ret[3] + 1
14     print("--------------------begin pack data and begin send to c++")
15     print("")
16     bin_buf_all = struct.pack(ii11si, buf1, buf2, "dfds", buf4)
17     print("----------------------------python end-----------------------")
18     return bin_buf_all

下面附上vs2013的工程屬性修改

技術分享

設置python工程的include路徑和libs路徑

技術分享

技術分享

接下來;就可以編譯輸出了;

----------import sys-------
test pyhon OK!

----------------------------python 1-----------------------
----------------------------python deal-----------------------
--------------------python receive c++ struct:
begin unpack:

(1, 2, ‘kjac\x00\xfe\xfe\xfe\xfe\xfe\xfe‘, 3)
--------------------begin pack data and begin send to c++

----------------------------python end-----------------------

-----------c++層接收py返回:buf1:2,buf2:3,buf3:dfds,buf4:4

技術分享

現在c++調用python已經大功告成了;下面就是python和c++之間的框架消息及測試代碼的構造

技術分享

c++調用python系列(1): 結構體作為入參及返回結構體