2017-03-14 5 views
1

Dans une tentative de recréer la fonction getenvironment(..) C de _winapi.c (direct link) en python ordinaire à l'aide ctypes, Je me demande comment le code C suivant pourrait être traduit:Construction d'un tampon de chaîne UCS4 en python 2.7 ctypes

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'; 

Il semble que la fonction ctypes.create_unicode_buffer(..) (doc, code) fait quelque chose d'assez près que je pouvais reproduire si je pouvais avoir un accès à Py_UCS4 type C ou être sûr de son lien vers un autre type accessible à python par ctypes.

Est-ce que c_wchar un bon candidat?, Mais il semble que je ne peux pas faire cette hypothèse, comme Python 2.7 peut être compilé pour UCS-2 si je ne me trompe pas (source), et je pense que les fenêtres attend vraiment fo UCS-4 il ... même s'il semble que ctypes.wintypes.LPWSTR est un alias à c_wchart_p dans cPython 2.7 (code).

Pour cette question, il est sûr de faire l'hypothèse que la plate-forme cible est python 2.7 sur Windows si cela aide.

Contexte (si elle a une certaine importance):

Je suis en train de plonger pour la première fois en ctypes pour tenter une solution python simple au bug de CPython 2.7 fenêtres frapper subprocess.Popen(..) mise en œuvre. This bug is a won't fix. Ce bug empêche l'utilisation d'unicode dans les appels de ligne de commande (comme nom ou arguments exécutables). Ceci est corrigé dans python 3, donc je vais essayer de mettre en œuvre en python inverse l'implémentation cPython3 réelle de la CreateProcess(..) requise en _winapi.c qui appelle à son tour getenvironment(..). Cette solution de contournement possible a été mentionnée dans les commentaires de this answer à une question relative aux problèmes d'unicode subprocess.Popen(..).

Répondre

0

Cela ne répond pas à la partie dans le titre sur la construction spécifiquement UCS4 buffer. Mais il donne une réponse partielle à la question en gras et parvient à créer un buffer unicode qui semble fonctionner sur mon python 2.7 actuel sur windows: (donc peut-être que UCS4 n'est pas nécessaire).

Nous supposons donc que c_wchar est ce que les fenêtres requièrent (si UCS4 ou UCS2 n'est pas encore clair pour moi, et cela pourrait ne pas avoir d'importance, mais je reconnais avoir une très faible confiance dans mes connaissances ici).

Voici donc le code python qui reproduit le code C comme demandé dans la 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" 

Cette wenv peut alors être amené à CreateProcessW et cela semble fonctionner.