我正在测试Python3.x的内置ctypes模块,然后再花一些时间为我现有的C库创建一个包装器。
我知道C中的stdlib函数需要对手册中标记为char *的任何内容进行ASCII码输入。但是,我的库是UTF-8兼容的,并且我已经在C程序中对其进行了测试。我还测试了在为C11编译时,以下代码是有效的,并按预期工作:
printf("Hello, %s!\n", u8"world");但是,如果我在Python中尝试执行相同的操作,则只打印字符串中的第一个字符。
from ctypes import *
libc = CDLL("libc.so.6")
libc.printf(b"Hello, %s!\n", "world") # will print: Hello, w!关于Unicode的Python3手册暗示Python3使用UTF-8作为其字符编码,这应该避免printf看到并停止读取的嵌入式NUL字节。如果我将Python测试中的%s更改为%ls,它将按预期打印。
Python真的在使用UTF-16吗?
发布于 2014-12-14 22:25:01
Python3(3.3之前的版本)在内部使用UCS-16或UCS-32,per the docs
字符串在内部存储为码点序列(准确地说,是Py_UNICODE数组)。根据Python的编译方式(通过--不带宽-unicode或--带宽-unicode,前者是默认的),Py_UNICODE可以是16位数据类型,也可以是32位数据类型。Py_UNICODE
此类型表示存储类型,Python在内部使用该存储类型作为保存Unicode序号的基础。Python的默认构建对Py_UNICODE使用16位类型,并在内部将Unicode值存储为UCS2。还可以构建Python的UCS4版本(大多数最新的Linux发行版都附带Python的UCS4版本)。然后,这些构建将32位类型用于Py_UNICODE,并在内部将Unicode数据存储为UCS4。
发布于 2014-12-15 13:22:56
下面这行是怎么回事:
libc.printf(b"Hello, %s!\n", "world") # will print: Hello, w!是ctypes将字节字符串编组为char*,将Unicode字符串编组为wchar_t* (UTF16或UTF32,取决于操作系统)。Python在内部使用什么并不重要。我在Windows上,所以我将使用cdll.msvcrt,但请注意,%s期望char*,而%ls期望用于printf的wchar_t*
from ctypes import *
cdll.msvcrt.printf(b'Hello, %s!\n', b'world') # byte string
cdll.msvcrt.printf(b'Hello, %ls!\n', 'world') # Unicode string (UTF-16 or UTF-32)
cdll.msvcrt.printf(b'Hello, %s!\n', 'world') # incorrect!输出:
Hello, world!
Hello, world!
Hello, w!在您的示例中,只需为%s使用一个字节字符串:
libc.printf(b"Hello, %s!\n", b"world")如果您希望使用UTF-8,您可以进行自己的显式编码:
#coding:utf8
from ctypes import *
cdll.msvcrt.printf(b'Hello, %s!\n', 'αßΓπΣσµτΦ'.encode('utf8'))输出(通过chcp 65001更改Windows控制台后,UTF-8代码页):
Hello, αßΓπΣσµτΦ!https://stackoverflow.com/questions/27470027
复制相似问题