尝试使用 ctypes
在纯 python 中重新创建 _winapi.c
( direct link ) 的 getenvironment(..)
C 函数>, 我想知道如何翻译以下 C 代码:
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';
似乎函数 ctypes.create_unicode_buffer(..)
(doc,code)正在做一些非常接近的事情,如果我可以访问 Py_UCS4
C 类型或确保它与 python 可通过 ctypes
访问的任何其他类型的链接。
c_wchar
会是一个很好的候选者吗?,但我似乎不能做出这样的假设,因为 python 2.7 可以在 UCS-2
中编译,如果我是对( source ),我猜 Windows 真的在等待 UCS-4
......即使看起来 ctypes.wintypes.LPWSTR
是一个别名c_wchart_p
在 cPython 2.7 ( code ) 中。
对于这个问题,如果有帮助的话,可以安全地假设目标平台是 Windows 上的 python 2.7。
上下文(如果它有一定的重要性):
我第一次在 ctypes
中钻研,尝试用普通的 python 修复 cPython 2.7 的 bug 命中 windows subprocess.Popen(..)
实现。 This bug is a won't fix .此错误会阻止在命令行调用中使用 unicode(作为可执行文件名称或参数)。这在 python 3 中已修复,因此我在纯 python 中反向实现 _winapi.c
中所需 CreateProcess(..)
的实际 cPython3 实现依次调用 getenvironment(..)
。
this answer 的评论中提到了这种可能的解决方法与 subprocess.Popen(..)
unicode 问题相关的问题。
最佳答案
这没有回答标题中关于专门构建 UCS4
缓冲区的部分。但它以粗体给出了问题的部分答案,并设法创建了一个 unicode 缓冲区,该缓冲区似乎适用于我当前在 Windows 上的 python 2.7:(因此可能不需要 UCS4)。
所以我们在这里假设 c_wchar
是 Windows 需要的(如果它是 UCS4 或 UCS2 对我来说还不是很清楚,它可能不重要,但我认为有一个对我在这里的知识非常自信)。
所以这是按照问题中的要求重现 C 代码的 python 代码:
## 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"
然后可以将此 wenv
馈送到 CreateProcessW
并且这似乎有效。
关于windows - 在 python 2.7 ctypes 中构建 UCS4 字符串缓冲区,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42780908/