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

 

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

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

 

開始:bash

首先是c++調用python這一層須要打通;服務器

幸運的是python本身有一套庫提供c/c++進行調用;架構

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

 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的工程屬性修改socket

設置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++之間的框架消息及測試代碼的構造

相關文章
相關標籤/搜索