c++调用python系列: 结构体作为入参及返回结构体

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++调用python系列: 结构体作为入参及返回结构体相关的知识,希望对你有一定的参考价值。

 

最近在打算用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系列: 结构体作为入参及返回结构体的主要内容,如果未能解决你的问题,请参考以下文章

C#和C++传递结构体

C++的一个函数的返回值可以是结构体吗?

IDA逆向笔记-C语言入参顺序约定和结构体

C#调用C++的dll库怎么传递结构体中不定长度的char数组

C语言中,结构体作为函数参数传递,详解?

C++编程基础: 13. 结构体与联合体