c++调用python系列(1): 结构体作为入参及返回结构体
最近在打算用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++之间的框架消息及测试代码的构造