2

In an attempt to recreate the getenvironment(..) C function of _winapi.c (direct link) in plain python using ctypes, I'm wondering how the following C code could be translated:

buffer = PyMem_NEW(Py_UCS4, totalsize);
if (! buffer) {
    PyErr_NoMemory();
    goto error;
}
p = buffer;
end = buffer + totalsize;

for (i = 0; i < envsize; i++) {
    PyObject* key = PyList_GET_ITEM(keys, i);
    PyObject* value = PyList_GET_ITEM(values, i);
    if (!PyUnicode_AsUCS4(key, p, end - p, 0))
        goto error;
    p += PyUnicode_GET_LENGTH(key);
    *p++ = '=';
    if (!PyUnicode_AsUCS4(value, p, end - p, 0))
        goto error;
    p += PyUnicode_GET_LENGTH(value);
    *p++ = '\0';
}

/* add trailing null byte */
*p++ = '\0';

It seems that the function ctypes.create_unicode_buffer(..) (doc, code) is doing something quite close that I could reproduce if only I could have an access to Py_UCS4 C type or be sure of its link to any other type accessible to python through ctypes.

Would c_wchar be a good candidate ?, but it seems I can't make that assumption, as python 2.7 could be compiled in UCS-2 if I'm right (source), and I guess windows is really waiting fo UCS-4 there... even if it seems that ctypes.wintypes.LPWSTR is an alias to c_wchart_p in cPython 2.7 (code).

For this question, it is safe to make the assumption that the target platform is python 2.7 on Windows if that helps.

Context (if it has some importance):

I'm in the process of delving for the first time in ctypes to attempt a plain python fix at cPython 2.7's bug hitting windows subprocess.Popen(..) implementation. This bug is a won't fix. This bug prevents the usage of unicode in command line calls (as executable name or arguments). This is fixed in python 3, so I'm having a go at reverse implementing in plain python the actual cPython3 implementation of the required CreateProcess(..) in _winapi.c which calls in turn getenvironment(..). This possible workaround was mentionned in the comments of this answer to a question related to subprocess.Popen(..) unicode issues.

Community
  • 1
  • 1
vaab
  • 9,685
  • 7
  • 55
  • 60

1 Answers1

0

This doesn't answer the part in the title about build specifically UCS4 buffer. But it gives a partial answer to the question in bold and manage to create a unicode buffer that seems to work on my current python 2.7 on windows: (so maybe UCS4 is not required).

So we are here taking the assumption that c_wchar is what windows require (if it is UCS4 or UCS2 is not so clear to me yet, and it might have no importance, but I recon having a very light confidence in my knowledge here).

So here is the python code that reproduces the C code as requested in the question:

## creation of buffer of size totalsize
wenv = (c_wchar * totalsize)()    
wenv.value = (unicode("").join([
    unicode("%s=%s\0") % (key, value)
    for k, v in env.items()])) + "\0"

This wenv can then be fed to CreateProcessW and this seems to work.

vaab
  • 9,685
  • 7
  • 55
  • 60