日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

Python之struct介绍及详解(与C/C++通信结构体的交互)

發(fā)布時(shí)間:2025/3/15 c/c++ 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python之struct介绍及详解(与C/C++通信结构体的交互) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

用處

  • 按照指定格式將Python數(shù)據(jù)轉(zhuǎn)換為字符串,該字符串為字節(jié)流,如網(wǎng)絡(luò)傳輸時(shí),不能傳輸int,此時(shí)先將int轉(zhuǎn)化為字節(jié)流,然后再發(fā)送;
  • 按照指定格式將字節(jié)流轉(zhuǎn)換為Python指定的數(shù)據(jù)類型;
  • 處理二進(jìn)制數(shù)據(jù),如果用struct來處理文件的話,需要用’wb’,’rb’以二進(jìn)制(字節(jié)流)寫,讀的方式來處理文件;
  • 處理c語言中的結(jié)構(gòu)體;
    ?
  • struct模塊中的函數(shù)

    函數(shù)returnexplain
    pack(fmt,v1,v2…)string按照給定的格式(fmt),把數(shù)據(jù)轉(zhuǎn)換成字符串(字節(jié)流),并將該字符串返回.
    pack_into(fmt,buffer,offset,v1,v2…)None按照給定的格式(fmt),將數(shù)據(jù)轉(zhuǎn)換成字符串(字節(jié)流),并將字節(jié)流寫入以offset開始的buffer中.(buffer為可寫的緩沖區(qū),可用array模塊)
    unpack(fmt,v1,v2…..)tuple按照給定的格式(fmt)解析字節(jié)流,并返回解析結(jié)果
    pack_from(fmt,buffer,offset)tuple按照給定的格式(fmt)解析以offset開始的緩沖區(qū),并返回解析結(jié)果
    calcsize(fmt)size of fmt計(jì)算給定的格式(fmt)占用多少字節(jié)的內(nèi)存,注意對(duì)齊方式

    格式化字符串

    當(dāng)打包或者解包的時(shí),需要按照特定的方式來打包或者解包.該方式就是格式化字符串,它指定了數(shù)據(jù)類型,除此之外,還有用于控制字節(jié)順序、大小和對(duì)齊方式的特殊字符.

    對(duì)齊方式

    為了同c中的結(jié)構(gòu)體交換數(shù)據(jù),還要考慮c或c++編譯器使用了字節(jié)對(duì)齊,通常是以4個(gè)字節(jié)為單位的32位系統(tǒng),故而struct根據(jù)本地機(jī)器字節(jié)順序轉(zhuǎn)換.可以用格式中的第一個(gè)字符來改變對(duì)齊方式.定義如下

    CharacterByte orderSizeAlignment
    @(默認(rèn))本機(jī)本機(jī)本機(jī),湊夠4字節(jié)
    =本機(jī)標(biāo)準(zhǔn)none,按原字節(jié)數(shù)
    <小端標(biāo)準(zhǔn)none,按原字節(jié)數(shù)
    >大端標(biāo)準(zhǔn)none,按原字節(jié)數(shù)
    !network(大端)標(biāo)準(zhǔn)none,按原字節(jié)數(shù)

    如果不懂大小端,見大小端參考網(wǎng)址.

    格式符

    格式符C語言類型Python類型Standard size
    xpad byte(填充字節(jié))no value?
    ccharstring of length 11
    bsigned charinteger1
    Bunsigned charinteger1
    ?_Boolbool1
    hshortinteger2
    Hunsigned shortinteger2
    iintinteger4
    I(大寫的i)unsigned intinteger4
    l(小寫的L)longinteger4
    Lunsigned longlong4
    qlong longlong8
    Qunsigned long longlong8
    ffloatfloat4
    ddoublefloat8
    schar[]string?
    pchar[]string?
    Pvoid *long?

    注- -!

  • _Bool在C99中定義,如果沒有這個(gè)類型,則將這個(gè)類型視為char,一個(gè)字節(jié);
  • q和Q只適用于64位機(jī)器;
  • 每個(gè)格式前可以有一個(gè)數(shù)字,表示這個(gè)類型的個(gè)數(shù),如s格式表示一定長度的字符串,4s表示長度為4的字符串;4i表示四個(gè)int;
  • P用來轉(zhuǎn)換一個(gè)指針,其長度和計(jì)算機(jī)相關(guān);
  • f和d的長度和計(jì)算機(jī)相關(guān);
  • 進(jìn)制轉(zhuǎn)化:

    # 獲取用戶輸入十進(jìn)制數(shù) dec = int(input("輸入數(shù)字:"))print("十進(jìn)制數(shù)為:", dec) print("轉(zhuǎn)換為二進(jìn)制為:", bin(dec)) print("轉(zhuǎn)換為八進(jìn)制為:", oct(dec)) print("轉(zhuǎn)換為十六進(jìn)制為:", hex(dec))
    • 16進(jìn)制轉(zhuǎn)10進(jìn)制: int('0x10', 16) ?==> ?16

    Python沒有專門處理字節(jié)的數(shù)據(jù)類型。但由于b'str'可以表示字節(jié),所以,字節(jié)數(shù)組=二進(jìn)制str。而在C語言中,我們可以很方便地用struct、union來處理字節(jié),以及字節(jié)和int,float的轉(zhuǎn)換。

    在Python中,比方說要把一個(gè)32位無符號(hào)整數(shù)變成字節(jié),也就是4個(gè)長度的bytes,你得配合位運(yùn)算符這么寫:

    >>> n = 10240099 >>> b1 = (n & 0xff000000) >> 24 >>> b2 = (n & 0xff0000) >> 16 >>> b3 = (n & 0xff00) >> 8 >>> b4 = n & 0xff >>> bs = bytes([b1, b2, b3, b4]) >>> bs b'\x00\x9c@c'

    非常麻煩。如果換成浮點(diǎn)數(shù)就無能為力了。

    好在Python提供了一個(gè)struct模塊來解決bytes和其他二進(jìn)制數(shù)據(jù)類型的轉(zhuǎn)換。

    ?

    pack

    structpack函數(shù)把任意數(shù)據(jù)類型變成bytes

    >>> import struct >>> struct.pack('>I', 10240099) b'\x00\x9c@c'

    pack的第一個(gè)參數(shù)是處理指令,'>I'的意思是:

    >表示字節(jié)順序是big-endian,也就是網(wǎng)絡(luò)序,I表示4字節(jié)無符號(hào)整數(shù)。

    后面的參數(shù)個(gè)數(shù)要和處理指令一致。

    ?

    unpack

    unpackbytes變成相應(yīng)的數(shù)據(jù)類型:

    >>> struct.unpack('>IH', b'\xf0\xf0\xf0\xf0\x80\x80') (4042322160, 32896)

    根據(jù)>IH的說明,后面的bytes依次變?yōu)?strong>I:4字節(jié)無符號(hào)整數(shù)和H:2字節(jié)無符號(hào)整數(shù)。

    所以,盡管Python不適合編寫底層操作字節(jié)流的代碼,但在對(duì)性能要求不高的地方,利用struct就方便多了。

    ?

    struct模塊定義的數(shù)據(jù)類型可以參考Python官方文檔:

    https://docs.python.org/3/library/struct.html#format-characters

    Windows的位圖文件(.bmp)是一種非常簡單的文件格式,我們來用struct分析一下。

    首先找一個(gè)bmp文件,沒有的話用“畫圖”畫一個(gè)。

    讀入前30個(gè)字節(jié)來分析:

    >>> s = b'\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00'

    BMP格式采用小端方式存儲(chǔ)數(shù)據(jù),文件頭的結(jié)構(gòu)按順序如下:

    兩個(gè)字節(jié):'BM'表示W(wǎng)indows位圖,'BA'表示OS/2位圖;一個(gè)4字節(jié)整數(shù):表示位圖大小;一個(gè)4字節(jié)整數(shù):保留位,始終為0;一個(gè)4字節(jié)整數(shù):實(shí)際圖像的偏移量;一個(gè)4字節(jié)整數(shù):Header的字節(jié)數(shù);一個(gè)4字節(jié)整數(shù):圖像寬度;一個(gè)4字節(jié)整數(shù):圖像高度;一個(gè)2字節(jié)整數(shù):始終為1;一個(gè)2字節(jié)整數(shù):顏色數(shù)

    所以,組合起來用unpack讀取:

    >>> struct.unpack('<ccIIIIIIHH', s) (b'B', b'M', 691256, 0, 54, 40, 640, 360, 1, 24)

    結(jié)果顯示,b'B'b'M'說明是Windows位圖,位圖大小為640x360,顏色數(shù)為24。

    請(qǐng)編寫一個(gè)bmpinfo.py,可以檢查任意文件是否是位圖文件,如果是,打印出圖片大小和顏色數(shù)。

    # -*- coding: utf-8 -*-import base64,structbmp_data = base64.b64decode('Qk1oAgAAAAAAADYAAAAoAAAAHAAAAAoAAAABABAAAAAAADICAAASCwAAEgsAAAAAAAAAAAAA/3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9/AHwAfAB8AHwAfAB8AHwAfP9//3//fwB8AHwAfAB8/3//f/9/AHwAfAB8AHz/f/9//3//f/9//38AfAB8AHwAfAB8AHwAfAB8AHz/f/9//38AfAB8/3//f/9//3//fwB8AHz/f/9//3//f/9//3//f/9/AHwAfP9//3//f/9/AHwAfP9//3//fwB8AHz/f/9//3//f/9/AHwAfP9//3//f/9//3//f/9//38AfAB8AHwAfAB8AHwAfP9//3//f/9/AHwAfP9//3//f/9//38AfAB8/3//f/9//3//f/9//3//fwB8AHwAfAB8AHwAfAB8/3//f/9//38AfAB8/3//f/9//3//fwB8AHz/f/9//3//f/9//3//f/9/AHwAfP9//3//f/9/AHwAfP9//3//fwB8AHz/f/9/AHz/f/9/AHwAfP9//38AfP9//3//f/9/AHwAfAB8AHwAfAB8AHwAfAB8/3//f/9/AHwAfP9//38AfAB8AHwAfAB8AHwAfAB8/3//f/9//38AfAB8AHwAfAB8AHwAfAB8/3//f/9/AHwAfAB8AHz/fwB8AHwAfAB8AHwAfAB8AHz/f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//3//f/9//38AAA==')def bmp_info(data): str = struct.unpack('<ccIIIIIIHH',data[:30]) #bytes類也有切片方法if str[0]==b'B' and str[1]==b'M':print("這是位圖文件")return {'width': str[-4],'height': str[-3],'color': str[-1]}else:print("這不是位圖文件")if __name__ == '__main__':bmp_info(bmp_data)print('ok')

    示例:

    現(xiàn)在我們有了格式字符串,也知道了封裝函數(shù),那現(xiàn)在先通過一兩個(gè)例子看一看。

    ?例一:比如有一個(gè)報(bào)文頭部在C語言中是這樣定義的

    struct header {unsigned short? usType;char[4]?????????acTag;unsigned int????uiVersion;unsigned int????uiLength; };

    在C語言對(duì)將該結(jié)構(gòu)體封裝到一塊緩存中是很簡單的,可以使用memcpy()實(shí)現(xiàn)。在Python中,使用struct就需要這樣:

    str = struct.pack('B4sII', 0x04, 'aaaa', 0x01, 0x0e)

    'B4sII'? ------?? 有一個(gè)unsigned short、char[4], 2個(gè)unsigned int。其中s之前的數(shù)字說明了字符串的大小?。

    type, tag, version, length = struct.unpack('B4sll', str)

    ?

    class struct.Struct(format)

    返回一個(gè)struct對(duì)象(結(jié)構(gòu)體,參考C)。

    該對(duì)象可以根據(jù)格式化字符串的格式來讀寫二進(jìn)制數(shù)據(jù)。

    第一個(gè)參數(shù)(格式化字符串)可以指定字節(jié)的順序。

    默認(rèn)是根據(jù)系統(tǒng)來確定,也提供自定義的方式,只需要在前面加上特定字符即可:

    struct.Struct('>I4sf')

    常見方法和屬性:

    方法

    pack (v1, v2, …)

    返回一個(gè)字節(jié)流對(duì)象。

    按照fmt(格式化字符串)的格式來打包參數(shù)v1,v2,...。

    通俗的說就是:

    首先將不同類型的數(shù)據(jù)對(duì)象放在一個(gè)“組”中(比如元組(1,'good',1.22)),

    然后打包(“組”轉(zhuǎn)換為字節(jié)流對(duì)象),最后再解包(將字節(jié)流對(duì)象轉(zhuǎn)換為“組”)。

    pack_into(buffer, offset, v1, v2, …)

    根據(jù)格式字符串fmt包裝值v1,v2,...,并將打包的字節(jié)寫入從位置偏移開始的可寫緩沖buffer。?請(qǐng)注意,offset是必需的參數(shù)。

    unpack_from(buffer, offset=0)

    根據(jù)格式字符串fmt,從位置偏移開始從緩沖區(qū)解包。 結(jié)果是一個(gè)元組,即使它只包含一個(gè)項(xiàng)目。?緩沖區(qū)的大小(以字節(jié)為單位,減去偏移量)必須至少為格式所需的大小,如calcsize()所反映的。

    屬性

    format

    格式化字符串。

    size

    結(jié)構(gòu)體的大小。


    實(shí)例:

    1. 通常的打包和解包

    # -*- coding: utf-8 -*- """ 打包和解包 """ import?struct import binasciivalues = (1, b'good', 1.22) #查看格式化對(duì)照表可知,字符串必須為字節(jié)流類型。 s =?struct.Struct('I4sf') packed_data = s.pack(*values) unpacked_data = s.unpack(packed_data)print('Original values:', values) print('Format string :', s.format) print('Uses :', s.size,?'bytes') print('Packed Value :', binascii.hexlify(packed_data)) print('Unpacked Type :', type(unpacked_data),?' Value:', unpacked_data)

    ?結(jié)果:

    Original values: (1, b'good', 1.22)
    Format string : b'I4sf'
    Uses : 12 bytes
    Packed Value : b'01000000676f6f64f6289c3f'
    Unpacked Type : <class 'tuple'> ?Value: (1, b'good', 1.2200000286102295)

    說明:

    首先將數(shù)據(jù)對(duì)象放在了一個(gè)元組中,然后創(chuàng)建一個(gè)Struct對(duì)象,并使用pack()方法打包該元組;最后解包返回該元組。

    這里使用到了binascii.hexlify(data)函數(shù)。

    binascii.hexlify(data)

    返回字節(jié)流的十六進(jìn)制字節(jié)流。

    >>> a = 'hello' >>> b = a.encode() >>> b b'hello' >>> c = binascii.hexlify(b) >>> c b'68656c6c6f'

    ?

    2. 使用buffer來進(jìn)行打包和解包

    使用通常的方式來打包和解包會(huì)造成內(nèi)存的浪費(fèi),所以python提供了buffer的方式:

    # -*- coding: utf-8 -*- """ 通過buffer方式打包和解包 """ import?struct import binascii import ctypesvalues = (1, b'good', 1.22) #查看格式化字符串可知,字符串必須為字節(jié)流類型。 s =?struct.Struct('I4sf') buff = ctypes.create_string_buffer(s.size) packed_data = s.pack_into(buff,0,*values) unpacked_data = s.unpack_from(buff,0)print('Original values:', values) print('Format string :', s.format) print('buff :', buff) print('Packed Value :', binascii.hexlify(buff)) print('Unpacked Type :', type(unpacked_data),?' Value:', unpacked_data)

    ?結(jié)果:

    Original values1: (1, b'good', 1.22)
    Original values2: (b'hello', True)
    buff : <ctypes.c_char_Array_18 object at 0x000000D5A5617348>
    Packed Value : b'01000000676f6f64f6289c3f68656c6c6f01'
    Unpacked Type : <class 'tuple'>??Value: (1, b'good', 1.2200000286102295)

    說明:

    針對(duì)buff對(duì)象進(jìn)行打包和解包,避免了內(nèi)存的浪費(fèi)。

    這里使用到了函數(shù)

    ctypes.create_string_buffer(init_or_size,size = None)

    創(chuàng)建可變字符緩沖區(qū)。
    返回的對(duì)象是c_char的ctypes數(shù)組。

    init_or_size必須是一個(gè)整數(shù),它指定數(shù)組的大小,或者用于初始化數(shù)組項(xiàng)的字節(jié)對(duì)象。

    ?

    3. 使用buffer方式來打包多個(gè)對(duì)象

    # -*- coding: utf-8 -*- """ buffer方式打包和解包多個(gè)對(duì)象 """ import?struct import binascii import ctypesvalues1 = (1, b'good', 1.22) #查看格式化字符串可知,字符串必須為字節(jié)流類型。 values2 = (b'hello',True) s1 =?struct.Struct('I4sf') s2 =?struct.Struct('5s?') buff = ctypes.create_string_buffer(s1.size+s2.size) packed_data_s1 = s1.pack_into(buff,0,*values1) packed_data_s2 = s2.pack_into(buff,s1.size,*values2) unpacked_data_s1 = s1.unpack_from(buff,0) unpacked_data_s2 = s2.unpack_from(buff,s1.size)print('Original values1:', values1) print('Original values2:', values2) print('buff :', buff) print('Packed Value :', binascii.hexlify(buff)) print('Unpacked Type :', type(unpacked_data_s1),?' Value:', unpacked_data_s1) print('Unpacked Type :', type(unpacked_data_s2),?' Value:', unpacked_data_s2)

    ?結(jié)果:

    Original values2: (b'hello', True)
    buff : <ctypes.c_char_Array_18 object at 0x000000D5A5617348>
    Packed Value : b'01000000676f6f64f6289c3f68656c6c6f01'
    Unpacked Type : <class 'tuple'> ?Value: (1, b'good', 1.2200000286102295)
    Unpacked Type : <class 'tuple'> ?Value: (b'hello', True)

    總結(jié)

    以上是生活随笔為你收集整理的Python之struct介绍及详解(与C/C++通信结构体的交互)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 日韩三级在线观看 | 一级高清视频 | 国产色综合网 | 国产精品5区 | 中文字幕一区二区不卡 | 黄片一区二区 | 色多多视频污 | 91大神在线免费观看 | 人成网站在线观看 | 色偷偷噜噜噜亚洲男人 | 黑丝久久| 伊人久久精品视频 | 午夜婷婷丁香 | 91一区二区三区在线观看 | 天堂av8| 日日夜夜爱爱 | 国产专区欧美专区 | 夜间福利视频 | 99久久九九| 69xxx国产| 成人精品动漫 | 视频在线观看一区二区三区 | 国产精品国产精品国产专区蜜臀ah | 亚洲天天干| 一区二区成人网 | 人体私拍套图hdxxxx | 好爽…又高潮了毛片免费看 | 精品免费国产 | 欧美日韩三级在线 | 亚洲精品日韩在线 | 国产资源站 | 啪啪.com| 四虎国产在线 | 成人午夜免费在线观看 | 国产精品爽爽久久 | 青青草污| 免费一级淫片 | 一本之道高清无码视频 | 国产手机在线播放 | 亚洲视频在线一区二区 | 五月综合激情 | 456亚洲影院 | 欧美性久久 | 欧美视频www | 开心激情综合网 | 中日韩在线播放 | 波多野结衣在线观看一区二区 | 最近的中文字幕在线看视频 | 一出一进一爽一粗一大视频 | 亚洲欧美综合一区 | 国产毛片18 | www国产成人| 久久成人亚洲 | 精品福利一区 | 欧美大片一区二区 | 成年免费视频 | 91视频在线观看视频 | 日日夜夜亚洲 | 调教少妇视频 | 午夜电影福利网 | 国产精品色图 | 人妻互换一区二区激情偷拍 | 99精品区 | 精品+无码+在线观看 | 成人涩涩软件 | 日韩一级在线观看视频 | 亚洲作爱视频 | 男人的天堂影院 | 国产一av | 日韩精品人妻一区二区三区免费 | 欧美国产日韩一区 | 呦呦色 | 韩国伦理电影免费在线 | 波多野结衣大片 | 女同在线观看 | 阿的白色内裤hd中文 | 中文字幕精品亚洲 | 伊人久久大香线蕉 | 伊人久久久久噜噜噜亚洲熟女综合 | 婷婷色在线观看 | 成人免费视频软件网站 | 8mav在线| 国产极品91 | 天天色成人网 | 亚洲性视频网站 | 91视频在线网站 | 成人小片| av老司机在线播放 | 欧美日韩第一区 | 奇米精品一区二区三区四区 | 重囗味sm一区二区三区 | 亚洲无av在线中文字幕 | 中文字幕在线视频一区二区三区 | 美女让男生桶 | 日韩aaa | 操网站| 国产成人手机在线 | 亚洲欧美日韩国产一区二区三区 | 噜噜av|