python struct pack string_python与C/C++中基本类型的相互转换 struct.pack

使用struct.pack一定要注意是在64位系统还是32位系统。

如struct.pack('L', 1) 返回长度在64位系统 返回长度是8,32位系统 回返是4

以下自己写个转换算法

DWORD_LEN = 4 #为32位系统

CONST_SQRT = [256 ** i for i in range(DWORD_LEN)]

def _PyInt_to_CBinStr(nVal):

'''把py的int转 成C中的int,返回py的str,即C中int的二进制形式;

注:转换时,以低字节在前面,即intel CPU字节排序方式。'''

retBinStr = ''

for i in range(DWORD_LEN -1, -1, -1):

retBinStr =  '%c%s' % (chr(nVal / CONST_SQRT[i]),   retBinStr)

nVal %=  CONST_SQRT[i]

return retBinStr

def _CBinStr_Int_to_PyInt(str_CBin):

'''把C形式的二进制int转 成py的int。

注:转换时,以低字节在前面,即intel CPU字节排序方式。'''

nPyInt = 0

for i in range(DWORD_LEN):

nPyInt += ord(str_CBin[i]) * CONST_SQRT[i]

return nPyInt

今天遇到个用python 以二进制方式写文件的问题,想把 py中的 数值写进文件,如下:

f = open(r'c:/t.bin', 'wb')

f.writer(1) # 这里是不能直接转数值参数的,要作个转换成二进制buff

上面这个转,浪费偶超多时间查资料。。。。

t;p>最终py的内置库可以作转换 struct

import struct

strBuff = struct.pack('L'. 1)

f.write(strBuff)

关于 struct.pack 的第一个参数 fmt ---转换方式,内置文档中有说明,也害找了很久。。。

对应表如下:

fmt参数:

Format

quot;>C Type

Python

Notes

x

pad byte

no value

c

char

string of length 1

b

signed char

integer

B

unsigned char

integer

h

short

integer

H

s="ctype">unsigned short

integer

i

int

integer

I

unsigned int

long

l

long

integer

L

unsigned long

long

q

long long

long

(1)

Q

unsigned long long

long

(1)

f

float

float

d

double

float

s

char[]

string

p

char[]

string

P

void *

integer

这两天做TCP协议,数据的传输都是二进制的,需要解释,于是用到了struct

看到这样一句代码:

length = struct.unpack('>I', self.buffer[:4])[0]

当时没有明白format=">I"是什么意思,从google找了一下,有人说这个东西,可都是比较笼统,没能让我明白,于是硬着头皮看API:

By default, C numbers are represented in the machine’s native format and byte order, and properly aligned by skipping pad bytes if necessary (according to the rules used by the C compiler).

通常,C语言下数字都是机器语言的格式并且按照字节排序,同时在需要的情况下会利用跳过填补的字节来进行适当的调整

Alternatively, the first character of the format string can be used to indicate the byte order, size and alignment of the packed data。

非此即彼:字符串的第一个字符要么被用于表示字符串的字节的排序,或者是字符串的size,还有就是数据是否对准。

Native byte order is big-endian or little-endian, depending on the host system. For example, Motorola and Sun processors are big-endian; Intel and DEC processors are little-endian.

计算机的字节序要么是高位顺序,要么是低位的,这依赖于主机本身。比如,摩托罗拉和sun的处理器是高位的,但是intel和DEC的是低位的。

这样子就明白了上面的format=">I"的意思,也就是说按照高位顺序来格式化取得一个int或long值。下面问题就又来了,你怎么知道读取的就是一个int或long值呢?

通过看struct的文档,可以看到struct通过两张表制定了一定的format规则,我按照自己的观察,给他归纳为两类,一个是和C当中类型的对照,另一个就是选择按照高位还是低位来解释字节。上面已经说了高低字节顺序,那么观察和C对照的表格,发现I 代表的就是integer or long ,详细的可以去看python的API。

下面是一些使用的例子,具体的使用,可以参考这些例子:

# 取前5个字符,跳过4个字符华,再取3个字符

format = '5s 4x 3s'

2. 使用struck.unpack获取子字符串

import struct

print struct.unpack(format, 'Test astring')

#('Test', 'ing')

来个简单的例子吧,有一个字符串'He is not very happy',处理一下,把中间的not去掉,然后再输出。

import struct

theString = 'He is not very happy'

format = '2s 1x 2s 5x 4s 1x 5s'

print ' '.join(struct.unpack(format, theString))

输出结果:

He is very happy

随后是关于网络字节的东东,从网上看来的,感觉有用:

Python的socket库采用string类型来发送和接收数据,这样当我们用

i = socket.recv(4)

来接收一个4字节的整数时,该整数实际上是以二进制的形式保存在字符串 i 的前4个字节中;大多数的时候我们需要的是一个真正的integer/long型,而不是一个用string型表示的整型。这时我们可以使用struct库:Interpret

strings as packed binary data. 对上面的情况,我们可以写 t = unpack("I", i) 第一个参数是格式化字符串,I指明字符串 i 包含的头一个数据项是一个以C语言的unsigned integer表示的整数,这里 i 只包含了一个数据项,实际上这个被解释的字符串也可以包含多个数据项,只要在格式化字符串里为每项数据指明一个格式即可;自然地,unpack返回的就是一个tuple类型了。

要将Python接受到的视频图像在C语言的Qt窗口显示,你可以使用以下步骤: 1. 在Python使用OpenCV等库捕获视频帧。 2. 将视频帧转换为Qt支持的图像格式,如QImage。 3. 将QImage传递给C++的Qt程序,可以使用Socket或共享内存等方式进行进程间通信。 4. 在C++使用Qt的界面库,在窗口显示QImage。 具体实现方法可以参考以下步骤: 1. 在Python使用OpenCV等库捕获视频帧: ```python import cv2 cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() # 处理帧 # 转换为Qt支持的图像格式 qimage = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888) ``` 2. 将QImage传递给C++的Qt程序: 在Python可以使用socket或共享内存等方式将QImage传递给C++的Qt程序。以下是使用socket方式实现的示例代码: ```python import socket import struct def send_qimage(qimage): # 创建socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 连接服务器 sock.connect(('localhost', 8888)) # 转换为bytes格式 data = qimage.bits().asstring(qimage.byteCount()) # 打包数据 header = struct.pack('lll', qimage.width(), qimage.height(), len(data)) # 发送数据头 sock.send(header) # 发送数据 sock.sendall(data) # 关闭socket sock.close() ``` 在C++可以使用socket编写服务器端程序,接收Python发送的QImage数据。 3. 在C++使用Qt的界面库,在窗口显示QImage: 在C++可以使用Qt的界面库,在窗口显示QImage。以下是显示QImage的示例代码: ```c++ #include <QtWidgets/QApplication> #include <QtGui/QImage> #include <QtGui/QPainter> #include <QtGui/QPixmap> #include <QtGui/QWindow> #include <QtNetwork/QTcpServer> #include <QtNetwork/QTcpSocket> #include <iostream> int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建窗口 QWidget window; window.show(); // 创建服务器 QTcpServer server; server.listen(QHostAddress::Any, 8888); // 监听连接请求 QObject::connect(&server, &QTcpServer::newConnection, [&](){ // 接受连接 QTcpSocket *socket = server.nextPendingConnection(); QObject::connect(socket, &QTcpSocket::readyRead, [=](){ // 读取数据头 char header[12]; socket->read(header, sizeof(header)); int width, height, size; std::memcpy(&width, header, 4); std::memcpy(&height, header + 4, 4); std::memcpy(&size, header + 8, 4); // 读取数据 QByteArray data = socket->read(size); QImage qimage((const uchar *)data.constData(), width, height, QImage::Format_RGB888); // 在窗口显示 QPixmap pixmap = QPixmap::fromImage(qimage); QPainter painter(&window); painter.drawPixmap(0, 0, pixmap); }); }); // 运行应用程序 return app.exec(); } ``` 以上代码,服务器监听端口8888,并在接收到Python发送的QImage数据时,在窗口显示QImage。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值