问题描述
extern ushort* getSomeStringW(ushort* Dest,int MaxLen);
该函数更改Dest
缓冲区并返回。
我用ctypes包装它。由于该库始终返回16位编码的字符串,因此我必须显式使用c_ushort
或c_uint16
缓冲区,而不能仅使用ctypes c_wchar_t
方法创建create_unicode_buffer
缓冲区。 (c_wchar_t
在Win上是16位,在OSX上是32位)
因此,我这样调用库:
dest = (ctypes.c_uint16 * MaxLen)()
result = library.getSomeStringW(byref(dest),MaxLen)
这按预期工作。有趣的是,ctypes似乎猜测返回类型,结果是一个python字符串。之后,我还可以访问dest
缓冲区中的内容,并将其显式解码为utf-16。
尽管如此,我仍然考虑过指定函数的restype
,但奇怪的是,此后结果还是错误的。
dest = (ctypes.c_uint16 * MaxLen)()
library.getSomeStringW.restype = ctypes.c_uint16 * MaxLen
result = library.getSomeStringW(byref(dest),MaxLen)
result
数组看起来与dest
数组不同。我知道数组可能没有引用相同的内存位置(至少这是我对ctypes文档所做的操作),但我仍然不明白为什么结果ctypes对象未正确填充。
当我使用numpy ctypelib并将restype
声明为
import numpy as np
library.getSomeStringW.restype = np.ctypeslib.ndpointer(ctypes.c_uint16,shape=(MaxLen,))
...这让我更加困惑。
在无法正常工作的情况下,dest
数组看起来就像我期望的那样
0000 = {int} 52
0001 = {int} 46
0002 = {int} 49
0003 = {int} 48
0004 = {int} 46
0005 = {int} 50
0006 = {int} 46
0007 = {int} 50
0008 = {int} 56
0009 = {int} 56
0010 = {int} 53
0011 = {int} 0
0012 = {int} 0
...
1000 = {int} 0
result
数组看起来像
0000 = {int} 53920
0001 = {int} 25850
0002 = {int} 321
0003 = {int} 0
0004 = {int} 63968
0005 = {int} 35350
0006 = {int} 32764
0007 = {int} 0
0008 = {int} 52816
0009 = {int} 47565
0010 = {int} 32764
0011 = {int} 0
0012 = {int} 39040
0013 = {int} 26425
0014 = {int} 321
0015 = {int} 0
...
每个第4个整数似乎都为0,这些值遍地都是(显然不是明智的utf-16字符值)
感谢您可能有任何想法!
解决方法
在注意到每次我运行代码时结果数组都会改变之后,我意识到我没有将结果设置为指针。
当然,numpy函数还会创建一个指针。
library.getSomeStringW.restype = ctypes.POINTER(ctypes.c_uint16 * MaxLen)
解决所有问题。