Python Ctypes Null Terminated String Block - python

I am using a ctypes implementation of CreateProcessWithLogonW, and everything works well except I cannot figure out how to handle this section:
A pointer to an environment block for the new process. If this parameter is NULL, the new process uses the environment of the calling process.
An environment block consists of a null-terminated block of null-terminated strings. Each string is in the following form:
name=value\0
To generated the raw string I execute the following:
lpEnvironment = '\0'.join(['%s=%s' % (k, os.environ[k]) for k in os.environ]) + '\0\0'
print lpEnvironment
'XAUTHORITY=/home/username/.Xauthority\x00MUTT_DIR=/home/username/.mutt\x00LASTDIRFILE=/home/username/.lastpwd-geany\x00LOGNAME=username\...\x00\x00'
However run I make a ctypes variable out of it, it truncates the information:
ctypes.c_wchar_p(lpEnvironment)
c_wchar_p(u'XAUTHORITY=/home/username/.Xauthority')
How can I pass the lpEnvironment information correctly?

As far as I can tell, the whole string does get passed across the ctypes boundary correctly in one direction, but gets truncated on the way back.
>>> ctypes.create_string_buffer('abc\0def').value
'abc'
>>> ctypes.create_string_buffer('abc\0def').raw
'abc\x00def'
Unfortunately (at least for me, Python 2.6.5 on Linux) the result of create_unicode_buffer doesn't have a .raw property. However,
>>> ctypes.wstring_at(ctypes.create_unicode_buffer(u'abc\0def), 7)
u'abc\x00def'
works as expected.

Related

How to get the printout from the results of a subprocess.run() function to appear the same as seen in a terminal?

import subprocess
result = subprocess.run(['pkexec', 'apt', 'update'], stdout=subprocess.PIPE)
print(result.stdout)
print(result.stdout) returned a very long string. See below.
pprint.pprint(result.stdout) returned the same content as a block of sentences. See below.
I would like the print out of result.stdout to be similar to the terminal print out when executing sudo apt update. How can I achieve it with python 3.6 found in Ubuntu 18.04?
The reason you get a block of "text" is that the output is not an actual string (which is utf-8 encoded in Python 3) but a bytes object. This is seen from the b being written in front of the text. In order to turn a bytes object into a string it needs to be "decoded."
To decode the bytes object the text.decode() method is used, for the particular string in this question that turns into
print(result.stdout.decode())
The bytes object can be of any coding, therefore the .decode() call accepts a parameter which tells which coding that is supposed to be decoded. The most common one is utf-8 so if no parameter is given, this is assumed. However, specifically on Windows systems, also other codings exists (e.g. "latin1"). To decode a "latin1" bytesobject the call would thus look like
print(text.decode("latin1"))
The opposite operation, which encodes a string to a bytes object is also available. Logically enough it is called .encode() and is typically used in protocols that stream the data to another destination (e.g. over the Internet or to disc). Also this call accepts code argument, that allows the text to be encoded as e.g. "latin1" even though the default is "utf-8".

GhPython vs Python: TypeErrorException from GH but not from Shell

I am using a library called py_openshowvar to communicate with a Kuka robot arm from grasshopper.
Everything works fine if I run the program from a command line python shell. However, when I run the same thing from GhPython, I get the following:
Not sure why I get the exceptions with GhPython but not when I run it outside the GH environment. The program still connects to the server and retrieves/sends the info I need, but I want to make sure and address this exception.
Thanks!
It is hard to tell you how to fix the error as you do not provide the code that triggers it, but in substance it comes from the fact that GHPython is IronPython (an implementation of Python based on .Net) whereas Python Shell is an implementation written in C.
The two implementations are similar but you sometimes hit a difference.
In your case the script is expecting a string or tuple but gets an IronPython.Runtime.Bytes.
Hmm, got bytes when expecting str looks like a unicode string vs byte string problem. You do no describe what are the versions of your CPython and GHPython, but you should know that Python 2 strings are byte strings while Python 3 ones are unicode strings.
If in Python 2 you can force a litteral string to be unicode by prepending it with u: u"foo" is a unicode string. You can also decode a byte string to its unicode version: b'ae\xe9\xe8'.decode('Latin1') is the unicode string u'aeéè'

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

Why python automatically returns character counts when write file

I recently noticed that when I have the following code:
File = "/dir/to/file"
Content = "abcdefg"
with open(File,"a") as f:
f.write(Content)
I got "7" as an output and it is the count of characters in the variable "Content". I do not recall seeing this (I used ipython notebook before, but this time I did it in the python environment in shell) and wonder if I did something wrong. My python version: Python 3.3.3. Thank you for your help.
As always this behaviour is normal for most .write() implementations, see also I/O Base Classes.
For example io.RawIOBase.write
Write the given bytes-like object, b, to the underlying raw stream, and return the number of bytes written.
or io.TextIOBase.write
Write the string s to the stream and return the number of characters written.
Which IO-class is used depends on (the OS and) the parameters given to open. But as far as I can see all of them return some sort of "characters" or "bytes" written count.

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