Python&C++混合编程-结构体参数传递

Python&C++混合编程-结构体参数传递


前言

本章介绍的是在使用Python&C++混合编程时,如何实现结构体参数的相互传递。混合编程的方式是由C++编写Python扩展库,然后直接在Python中import使用,这种方式于直接调用C++编写的动态连接库的实现方式不同。


一、结构体定义

  • Python代码定义
class test_st(Structure):
    _fields_ = [
        ('b1', c_uint8),
        ('b2', c_uint8),
        ('fp_bs', POINTER(c_uint8))
    ]

在Python中我们把结构体定义成一个类,这个类必须继承于Structure,在类中定义一个_fields_列表,并在其中以元组的方式列举结构体的成员变量。
元组内格式为(变量名称, 变量类型)。

  • C++代码定义
typedef struct
{
	uint8_t b1;
	uint8_t b2;
	uint8_t* fp_bs;
}TEST_ST;

二、实现方式

  • Python代码定义
from ctypes import *
import mymod

tt = test_st()
tt.b1 = 3
tt.b2 = 4
fp_bs = bytes([21, 22, 23])
BUFFER = c_char * len(fp_bs)
buffer = BUFFER()
memmove(buffer, fp_bs, len(fp_bs))
tt.fp_bs = cast(pointer(buffer), POINTER(c_uint8))

mymod.test(tt)

代码中必须要引用ctypes下的全部类型,这里定义了python和C++之间的转换类型。
mymod是我编写的C++扩展库。

  • C++代码定义
#include <stdio.h>
#include <memory.h>
#include <sys/time.h>
#include <Python.h>

//定义测试结构体
typedef struct
{
	uint8_t b1;
	uint8_t b2;
	uint8_t* fp_bs;
}TEST_ST;

//测试函数
static PyObject* mymod_test(PyObject* self, PyObject* args)
{
    printf("C++ - 测试结构体参数传递\r\n");
    PyObject* args1;
	//获取入口参数
    PyArg_ParseTuple(args, "O", &args1);

	//通过入口参数获取结构体指针
    Py_buffer data = {NULL, NULL};
    if(PyObject_GetBuffer(args1, &data, PyBUF_SIMPLE) != 0)
    {
        printf("C++ - 参数读取失败\r\n");
        return Py_None;
    }
    printf("C++ - 参数读取成功\r\n");
	
	//将指针转换为结构体指针
    TEST_ST* st = (TEST_ST*)data.buf;
    printf("C++ - 参数值:len-%lu, %x, %x, %x, %x, %x\r\n", sizeof(st), st->b1, st->b2, st->b3[0],st->b3[1],st->b3[2]);

	//在这里修改了结构体的变量,则Python中也会跟着改变
    st->b1 = 31;
    
    return Py_None;
}

#define MYMOD_TEST \
    { "test", (PyCFunction)mymod_test, METH_VARARGS, "test(Structure)." },

static PyMethodDef mymod_methods[] = {
    MYMOD_TEST
    {NULL, NULL, 0, NULL}
};

static PyModuleDef mymod_module = {
    PyModuleDef_HEAD_INIT,
    "mymod",
    "结构体参数传递测试类",
    0,
    mymod_methods
};

PyMODINIT_FUNC PyInit_mymod(void)
{
    return PyModule_Create(&mymod_module);
}

三、指针转换

本例的结构体中存在一个指针变量fp_bs,进行定义时我使用POINTER(数据类型)来指定变量是一个指针类型。在进行变量赋值时也需要给定指针,以本例来说,我们定义了一个字节数组,在Python代码中定义一个bytes(),长度是3个字节。我们使用ctypes 提供的类型转换方法 cast()将bytes转换为字节数值指针,实现如下

# 定义一个字节数组类
fp_bs = bytes([21, 22, 23])
# 将字节数组类转换为在内存里的字节数组
BUFFER = c_char * len(fp_bs)
buffer = BUFFER()
memmove(buffer, fp_bs, len(fp_bs))
# 获取字节数组的指针
tt.fp_bs = cast(pointer(buffer), POINTER(c_uint8))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vere

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值