1 回答
TA贡献1799条经验 获得超9个赞
原因是CTypes的微妙行为。当 c_char(以及c_wchar )数组作为结构中的字段存在时,它们会被静默转换为字节(或str )。这是通过以NUL终止的c_char_p(或c_wchar_p)完成的,这意味着如果遇到NUL(0x00 )字符,“数组”将被截断,这正是您的情况。您可以通过查看字段类型来检查。不知道为什么会这样(也许是为了方便使用),但在某些情况下它弊大于利。它可以用
仅限Python代码。
code00.py
#!/usr/bin/env python
import sys
import ctypes as ct
ARR_DIM = 10
CharArr = ct.c_char * ARR_DIM
class CharArrStruct(ct.Structure):
_fields_ = [
("data", CharArr),
]
def print_array(arr, text, size=ARR_DIM):
print(text)
for i in range(size):
print("{0:3d}".format(i), end=" - ")
try:
print(arr[i])
except IndexError:
print("IndexError!!!")
break
print()
def main(*argv):
arr = CharArr()
sarr = CharArrStruct()
print("Array (plain) type: {0:}".format(type(arr)))
print("Array (in structure) type: {0:}".format(type(sarr.data)))
string_separator = b"\x00"
print("\nString separator: {0:}".format(string_separator))
text = string_separator.join((b"abcd", b"efgh"))
arr[0:len(text)] = text
sarr.data = text
print_array(arr, "Plain array:")
print_array(sarr.data, "Structure with array:")
print("Strings (in structure): {0:}".format(sarr.data.split(string_separator)))
string_separator = b"\xFF"
print("\nString separator: {0:}".format(string_separator))
sarr.data = string_separator.join((b"abcd", b"efgh"))
print_array(sarr.data, "Structure with array:")
print("Strings (in structure): {0:}".format(sarr.data.split(string_separator)))
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main(*sys.argv[1:])
print("\nDone.")
输出:
e:\Work\Dev\StackOverflow\q060093054>"e:\Work\Dev\VEnvs\py_pc064_03.07.06_test0\Scripts\python.exe" code00.py
Python 3.7.6 (tags/v3.7.6:43364a7ae0, Dec 19 2019, 00:42:30) [MSC v.1916 64 bit (AMD64)] 64bit on win32
Array (plain) type: <class '__main__.c_char_Array_10'>
Array (in structure) type: <class 'bytes'>
String separator: b'\x00'
Plain array:
0 - b'a'
1 - b'b'
2 - b'c'
3 - b'd'
4 - b'\x00'
5 - b'e'
6 - b'f'
7 - b'g'
8 - b'h'
9 - b'\x00'
Structure with array:
0 - 97
1 - 98
2 - 99
3 - 100
4 - IndexError!!!
Strings (in structure): [b'abcd']
String separator: b'\xff'
Structure with array:
0 - 97
1 - 98
2 - 99
3 - 100
4 - 255
5 - 101
6 - 102
7 - 103
8 - 104
9 - IndexError!!!
Strings (in structure): [b'abcd', b'efgh']
Done.
备注:
如所见,数据字段类型已更改
我想到的最简单的解决方案是将字符串分隔符从NUL替换为您确定它不会出现在任何字符串中的另一个字符。我选择了0xFF ( 255 )。我认为包含 的结构也可以,但它会更复杂一些(另外,我没有测试它)
ctypes.POINTER(ctypes.c_char)
我的Fortran知识非常接近0,但是fortran2pystr看起来不太对劲。我不知道Fortran类型是如何构造的,但是从Python传递一个包装在结构指针中的char数组(实际上,它们具有相同的地址)并像普通char数组一样处理它似乎是错误的。更改struct可能会导致灾难
添加回答
举报