如何用ctypes确定以NULL结尾的字符串的长度?

时间:2018-03-30 20:41:01

标签: python python-3.x ctypes null-terminated

我通过ctypes访问一个函数,它返回一个指向以NULL结尾的字符串(字符数组/向量)的指针。内存由函数分配(不在我的控制之下)。问题是,它没有返回任何有关其长度的信息。我想出的东西(以及有效的东西),我在C中所做的事情的松散灵感,看起来有些古怪:

import ctypes

def get_length_of_null_terminated_string(in_pointer):
    datatype = ctypes.c_char
    datatype_size = ctypes.sizeof(datatype)
    terminator = b'\x00'
    length = 0
    char_pointer = ctypes.cast(in_pointer, ctypes.POINTER(datatype))
    STRING_MAX = 1024
    while True:
        if char_pointer.contents.value == terminator:
            break
        if length > STRING_MAX:
            raise
        void_pointer = ctypes.cast(char_pointer, ctypes.c_void_p)
        void_pointer.value += datatype_size
        char_pointer = ctypes.cast(void_pointer, ctypes.POINTER(datatype))
        length += 1
    return length

def test():
    test_string = b'Hello World!'
    print('Actual length: %d' % len(test_string))
    test_buffer = ctypes.create_string_buffer(test_string)
    test_pointer = ctypes.cast(test_buffer, ctypes.c_void_p)
    print('Measured length: %d' % get_length_of_null_terminated_string(test_pointer))

if __name__ == '__main__':
    test()

有更好的方法吗?

特别是,我找不到摆脱两个cast语句的方法。似乎我只能递增c_void_p对象的地址(通过其value属性),而指向c_char的指针似乎是不可能的。

1 个答案:

答案 0 :(得分:0)

感谢@abarnert在评论中提出建议。

在这里使用ctypes.POINTER(ctypes.c_char)是一种错误的方法。将我的指针转换为ctypes.c_char_p会有所帮助。 Python的len方法可以简单地应用于value实例的c_char_p属性。

按照我原来的例子,解决方案看起来像这样:

def get_length_of_null_terminated_string_better(in_pointer):
    return len(ctypes.cast(in_pointer, ctypes.c_char_p).value)