Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Print a C string in Python

Tags:

python

c

I want to print a C string using the Python print statement. The array vendorName contains the ASCIIZ C string A ANTHONY & SONS INC. My motivation is to convert the C string to a Python string such that I can use all of the Python string methods.

I have a struct:

class _vendrRecord(Structure):
    _pack_ = 1                                            # pack the struct
    _fields_ = [
        ("vendorName"            ,c_ubyte *(40 + 1)),
        ("ytdPayments"           ,c_ulong),
        ]

I want to print the string "vendorName" which is ASCIIZ.

I can print it using printf like this:

printf(b"%s\n", vendrRecord.vendorName)

I have tried this print(vendrRecord.vendorName) but it just prints the address. Based on information from Jamie Nicholl-Shelley, I tried print(cast(vendrRecord.vendorName,c_char_p).value) but that gives b'A ANTHONY & SONS INC'. I want simply A ANTHONY & SONS INC

Note that print(vendrRecord.ytdPayments) prints correctly.

like image 794
Eddy Avatar asked Jan 09 '16 20:01

Eddy


2 Answers

It looks like you've figured out most of it and are just confused about string encoding. You've managed to get to a bytes object:

>>> v.vendorName
<__main__.c_ubyte_Array_41 object at 0xb0994a04>
>>> cast(v.vendorName, c_char_p)
c_char_p(176882328)
>>> cast(v.vendorName, c_char_p).value
b'A ANTHONY & SONS INC'

The bytes object is what it sounds like, just a sequence of bytes -- it's only as a convenience for the user that it's shown in a stringlike way. Unlike a string, each component is an integer:

>>> cast(v.vendorName, c_char_p).value[7]
78

But since we know that we're using ascii, we can decode this bytes object into a Python string, and then use all of the usual methods on it:

>>> s = cast(v.vendorName, c_char_p).value.decode("ascii")
>>> s
'A ANTHONY & SONS INC'
>>> type(s)
<class 'str'>
>>> s.lower()
'a anthony & sons inc'
like image 82
DSM Avatar answered Sep 22 '22 18:09

DSM


You are printing the address as that is what you have asked the code to do. You have told it that it is a string type, but not declared it as a string in the function, instead use a pointer to the data at the address

Compared to print(), which figures this out for you as it a c++ based function

like image 22
Jamie Nicholl-Shelley Avatar answered Sep 23 '22 18:09

Jamie Nicholl-Shelley