[感谢您阅读本文,这让我很困扰。我正在使用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
就会被抹掉?
感谢您的时间,非常感谢。
这是我想出的。 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'