Serializing a C struct in Python and sending over a socket

2024/9/20 10:34:15

I'm trying to serializing the following C struct

struct packet
{int id;unsigned char *ce;unsigned char *syms;
};

in Python and send it over a socket. The number of elements pointed by ce and syms are known to be N. Currently I'm doing this way. First, I wrap the struct using ctypes to

class Packet(Structure):_fields_ = [("id",  c_int),("ce", POINTER(c_ubyte)),("syms", POINTER(c_ubyte))]

Then, I populate an object of the following class using its fill_data function from a ctypes.POINTER(Packet):

class DataLoad:def __init__(self):self.id = -1self.ce = []self.syms = []def fill_data(self, pkt_p):""" pkt_p is POINTER(Packet)"""self.id = pkt_p.contents.idself.ce = []for i in range(N):self.ce.append(pkt_p.contents.ce[i])self.syms = []for i in range(N):self.syms.append(pkt_p.contents.syms[i])

Finally, I simply use pickle.dumps(DataLoad) to generate a byte stream and send.

This approach works well. However, it seems to be quite slow. One reason I can see is that pickle.dumps bring much overhead. For example, if the C struct is only 1024 bytes, I may have to send almost 4000 bytes for each struct using pickle. Also, packing/populating DataLoad also takes time.

So my question is, do I have other better choices to serialize this C struct in python and send? I would prefer to avoid pickle and populate a separate class instance. Thanks.

Answer

Finally I figured out the following way to manually serialize the `Packet' instance without using pickle.

def serialize(pkt_p, size_g, size_p):""" Serialize Packet instancesize_g - number of elements pointed by cesize_p - number of elements pointed by symsReturn a byte stream""" pktstr = b''pktstr += struct.pack('i', pkt_p.contents.id)pktstr += string_at(pkt_p.contents.ce, size_g)pktstr += string_at(pkt_p.contents.syms, size_p)return pktstrdef deserialize(pkt_p, pktstr, size_g, size_p):""" De-serialize pktstr and fill a POINTER(Packet)"""pkt_p.contents.id = struct.unpack('i', pktstr[0:4])[0]ce = (c_ubyte * size_g).from_buffer_copy(pktstr[4:4+size_g])pkt_p.contents.ce = cast(ce, POINTER(c_ubyte))syms = (c_ubyte * size_p).from_buffer_copy(pktstr[-size_p:])pkt_p.contents.syms = cast(syms, POINTER(c_ubyte))

The string_at() and the from_buffer_copy() functions are the key.

https://en.xdnf.cn/q/72180.html

Related Q&A

creating multiple audio streams of an icecast2 server using python-shout

I am trying to create a web radio server to stream 3 sources at once. I am using python to create a source client for icecast2 using the python-shout library. I am not too familiar with the language (p…

Custom Deployment to Azure Websites

I recently started using Gulp.js to package all my CSS and JavaScript into single files, which I then include in my web app. My web app is written in Python (using Flask).I obviously dont want to track…

Python - Gspread Request Error 401

Im currently making a Discord-bot that connects to a Google-spreadsheet (gspread). But after Ive been running it for a while it starts to hand out errors and it cant connect to my gspread anymore (unle…

paramiko server mode port forwarding

I need to implement a ssh server using paramiko that only handles -R port forwarding requests like this:ssh -N -T -R 40005:destination_host:22 [email protected]So far from what i understand ill have to…

Pandas dataframe.hist() change title size on subplot?

I am manipulating DataFrame using pandas, Python. My data is 10000(rows) X 20(columns) and I am visualizing it, like this.df.hist(figsize=(150,150))However, if I make figsize bigger, each of subplots t…

Regex match back to a period or start of string

Id like to match a word, then get everything before it up to the first occurance of a period or the start of the string. For example, given this string and searching for the word "regex":s = …

Finding differences between strings

I have the following function that gets a source and a modified strings, and bolds the changed words in it.def appendBoldChanges(s1, s2):"Adds <b></b> tags to words that are changed&qu…

Python pandas: select 2nd smallest value in groupby

I have an example DataFrame like the following:import pandas as pd import numpy as np df = pd.DataFrame({ID:[1,2,2,2,3,3,], date:array([2000-01-01,2002-01-01,2010-01-01,2003-01-01,2004-01-01,2008-01-01…

How to disable SSL3 and weak ciphers with cherrypy builtin ssl module (python 3)

I have configured Cherrypy 3.8.0 with Python 3 to use SSL/TLS. However, I want to disable SSL3 to avoid POODLE. I searched through the documentation but I am unsure on how to implement it.I am using th…

cleaning big data using python

I have to clean a input data file in python. Due to typo error, the datafield may have strings instead of numbers. I would like to identify all fields which are a string and fill these with NaN using p…