Unpack data in python from C++ - python

Problem
I need to send 2 float from C++ to python, and vice-versa.
I am using the C++ library winsock2.h, and the function send() that requires the buffer to be char*.
I want to send, for example this string to python:
std::string string = "1 12.3"
My try
When using struct.unpack("..") python returns the wrong numbers.
I tried with many different values inside the string in unpack, but it never works.
How should I structure my unpack to work correctly? Thanks

Related

passing info from python to c prog

I created a C program and choose to use python as my GUI creator
I wrote the python GUI and decided to create a struct
typedef struct GUIcommunicator
{
char action[MAX_SIZE];
char params[MAX_PARAMS][MAX_SIZE];
}GUIcommunicator;
I using this answer I will return the
struct from the python receive him in my C code
but I don't know how.
And I'd like to some help
(the function that sends the struct (the python code) already got the action and the params as string list )
If you are developing a linux based application, you can perform Inter-Process Communication using FIFO files
For windows based applications, you could use Named-pipes
Regardless of the direction of the call, you end up with a PyObject* in C that refers to a list of strings. Fetch each element, then fetch the string data pointer and size for a Python 2 str or (the UTF-8 encoding of) a Python 3 str. Check the size against MAX_SIZE (probably MAX_SIZE-1) and beware of embedded null characters, which your struct presumably cannot represent.
There are of course ways of accepting any iterable, converting elements to strings, etc., if you want that flexibility.

Reading from I2C

I am reading a 24bit value using I2C in Raspberry Pi.
I open the /dev/i2c-1 file and then reading from it using the os.read function in python.
The transaction is being carried out correctly.
But the problem is even though I can access the register, when I try to store the value in a variable it doesn't work. According to the documentation of os.read(), if the EOF is reached, an empty string is returned and that's exactly my problem. How can I store the correct value?
Code below:
fd = os.open(filename,os.O_RDWR) //Opens the file
#The reason i use os.open instead of normal python open is that I
#need to access the linux C function.
def func(fd,addr):
os.write(fd,addr) // Sets the pointer to the register to be read.
x = os.read(fd,3) //Reads the value from the register.
print x //Prints an empty string
In order to cross check, I tried using the pigpio library. If I read using its function, it returns 2 values, count of the bytes read and the byte string itself.
What I noticed was that if I try to store the byte string, the one returned from the pigpio function, I still get an empty string when i print it on screen like this print(data).
What I think the problem is not of storing the data, but of properly formatting it .
So can anyone suggest how do I convert the byte string to an int value?
I know that there's one function for python 3. But I need to use python 2

Python Struct format error

So I am looking at code that I wrote perhaps as much as 4 years ago, and I know it ran correctly at the time. But now I am trying to run it, on a different computer than when I wrote it years ago and I am getting an error now. (Tried it today on both Windows 10 and Ubuntu)
I am using Python 2.7, as I was then too. I am using the Struct library to unpack C types from files, specifically I am trying to unpack 4 byte long values.
Here is the documentation for the 2.7 struct library. https://docs.python.org/2/library/struct.html
If you scroll down to the "Format Characters" section, you can see a table of the C types.
Here is my code:
bps = int(unpack('L', fmap[o+10:o+14])[0])
And here is the error I get.
error: unpack requires a string argument of length 8
The part that is confusing me is the "length 8" part. If I change the C type to "I" the code executes fine. But the documentation seems clear that "L" is 4 byte as well, and it worked in the past. I think I can use the "I" type for my purposes, but I am curious if any one else has seen this.
The standard size of L is 4 bytes, but that is only used if you are explicit about the endianness to use by beginning the format string with >, <, !, or =. Otherwise, the platform-dependent native size for your machine is used. (In this case, 8 bytes.)

When/why should I use struct library in python to pack and unpack?

I cant understand when should I use pack and unpack functions in struct library in python?
I also cant understand how to use them?
After reading about it, what I understood is that they are used to convert data into binary. However when I run some examples like:
>>> struct.pack("i",34)
'"\x00\x00\x00'
I cant make any sense out of it.
I want to understand its purpose, how these conversions take place, what does '\x' and other symbols represent/mean and how does unpacking work.
I cant understand when should I use pack and unpack functions in struct library in python?
Then you probably don't have cause to use them.
Other people deal with network and file formats that have low-level binary packing, where struct can be very useful.
However when I run some examples like:
>>> struct.pack("i",34)
'"\x00\x00\x00'
I cant make any sense out of it.
The \x notation is for representing individual bytes of your bytes object using hexadecimal. \x00 means that the byte's value is 0, \x02 means that byte's value is 2, \x10 means that that bytes value is 16, etc. " is byte 34, so we see a " instead of \x22 in this view of the string, but '\x22\x00\x00\x00' and '"\x00\x00\x00' are the same string
http://www.swarthmore.edu/NatSci/echeeve1/Ref/BinaryMath/NumSys.html might help you with some background if that is the level you need to understand numbers at.

How do I figure out the format for struct.unpack (because I didn't pack in Python)?

I have a C pipe client (pulled directly from the CallNamedPipe example found here) that, if given the string "first", sends the following message to my Python pipeserver:
b'f\x00i\x00r\x00s\x00t\x00\x00\x00'
The struct documentation gives examples where I did both the packing and unpacking in Python. That means I know the format because I explicitly specified it when I called struct.pack.
Is there some way for me to either a) infer the format from the above output or b) set the format in C the same way I do in Python?
Here's the relevant client code:
LPTSTR lpszPipename = TEXT("\\\\.\\pipe\\testpipe");
LPTSTR lpszWrite = TEXT("first");
fSuccess = CallNamedPipe(
lpszPipename, // pipe name
lpszWrite, // message to server
...
>>> b'f\x00i\x00r\x00s\x00t\x00\x00\x00'.decode('utf-16le')
u'first\x00'
"The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)"
Your C code is not writing a struct to the pipe, it is writing a null-terminated string encoded as little-endian UTF-16 text, which is produced by the TEXT() macro when you compile your Windows program in Unicode mode for an Intel CPU. Python knows how to decode these strings without using the struct module. Try this:
null_terminated_unicode_string = data.decode('utf-16le')
unicode_string = null_terminated_unicode_string[:-1]
You can use decode('utf-16') if your python code is running on the same CPU architecture as the C program that writes the data. You might want to read up on python's unicode codecs.
EDIT: You can infer the type of that data by knowing how UTF-16 and Windows string macros work, but python cannot infer it. You could set the string encoding in C the same way you would in python if you wanted to write some code to do so, but it's probably not worth your time.

Categories