范围内的ctypes字符串缓冲区

问题描述 投票:0回答:1

[感谢您阅读本文,这让我很困扰。我正在使用Python3.8,并使用ctypes调用DLL。在大多数情况下,ctypes就像魅力一样。

C DLL中的一个函数将输出名称列表,即

int get_date(char* names[]) // each name has length 10, with size of 5

在Python中,我成功地将其命名为

    string_buffers = [ctypes.create_string_buffer(10) for i in range(5)]
    char_array = (ctypes.c_char_p*5)(*map(ctypes.addressof, string_buffers))
    handler.get_date(char_array)

但是我试图排除一个函数来创建这种情况:

def create_char_p_array(length:int, size:int):
    string_buffers = [create_string_buffer(length) for i in range(size)]
    ia = (c_char_p*size)(*map(addressof, string_buffers))
    return ia

char_array = create_char_p_array(10,5)
handler.get_date(char_array) ### failed, or ,crashed, or random value ###

因此,为了缩小问题范围,我将map(addressof)移出了,这很神奇! :

def create_char_p_array(length:int, size:int):
    string_buffers = [create_string_buffer(length) for i in range(size)]
    return string_buffers

sbrs = create_char_p_array(10,5)
char_array = (c_char_p*5)(*map(addressof, sbrs ))
handler.get_date(char_array) # Success !

是因为一旦函数create_string_buffer返回,在函数作用域中创建的create_char_p_array就会被抹掉?

感谢您的时间,非常感谢。

python ctypes
1个回答
0
投票

这是我想出的。 addressof不会为其操作的对象创建引用。 cast将。

test.c:

#include <string.h>

__declspec(dllexport) int get_date(char* names[])
{
    strcpy_s(names[0],10,"One");
    strcpy_s(names[1],10,"Two");
    strcpy_s(names[2],10,"Three");
    strcpy_s(names[3],10,"Four");
    strcpy_s(names[4],10,"Five");
    return 5;
}

test.py:

from ctypes import *

dll = CDLL('./x')
dll.get_date.argtypes = POINTER(c_char_p),
dll.get_date.restype = c_int

def create_char_p_array(length:int, size:int):
    return (c_char_p*size)(*[cast(create_string_buffer(length),c_char_p) for _ in range(size)])

a = create_char_p_array(10,5)
dll.get_date(a)
for s in a:
    print(s)

输出:

b'One'
b'Two'
b'Three'
b'Four'
b'Five'
© www.soinside.com 2019 - 2024. All rights reserved.