ctypes参数从C++转Python及Python调用DLL的argtypes配置求助
解决Python中用ctypes调用C#声明的DLL函数问题
先来看你给出的C#函数声明:
[DllImport("test.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)] public static extern int function( byte[] filename, byte[] name, IntPtr result, out IntPtr UnmanagedStringArray, out int iStringsCountReceiver);
咱们逐个拆解参数对应的ctypes类型,再把完整的调用代码整理出来:
- byte[] filename 和 byte[] name:因为C#里设了
CharSet.Auto,如果这两个参数是用来传递字符串的,Python里可以先把字符串转成bytes类型,对应ctypes的c_char_p(适配系统默认ANSI编码);如果是Unicode场景,也可以用c_wchar_p直接传Python字符串,ctypes会自动处理编码转换。 - IntPtr result:这是一个通用指针,对应ctypes的
c_void_p。如果这个参数是需要传入的缓冲区,你得提前分配好对应大小的内存(比如用c.create_string_buffer);如果只是占位的空指针,直接传None即可(具体要看DLL的实际要求)。 - out IntPtr UnmanagedStringArray:
out标记这是输出参数,会返回一个字符串数组的指针。在ctypes里我们用POINTER(c_void_p)来定义这个参数类型,然后创建一个c_void_p变量,用byref传递进去接收返回值。 - out int iStringsCountReceiver:输出的整数类型,对应ctypes的
POINTER(c_int),创建一个c_int变量,用byref传递就能接收字符串数组的长度。
另外一定要设置函数的返回值类型,避免ctypes默认的返回值处理出错。
完整的Python代码示例如下:
import ctypes as c # 加载目标DLL mydll = c.cdll.LoadLibrary("test.dll") func = mydll.function # 配置参数类型 func.argtypes = [ c.c_char_p, # filename (byte[]) c.c_char_p, # name (byte[]) c.c_void_p, # result (IntPtr) c.POINTER(c.c_void_p), # out IntPtr UnmanagedStringArray c.POINTER(c.c_int) # out int iStringsCountReceiver ] # 配置返回值类型 func.restype = c.c_int # 准备调用参数 filename = b"your_target_filename" # 字符串转bytes name = b"your_name_input" result = None # 若需要传入缓冲区,替换为c.create_string_buffer(缓冲区大小) unmanaged_str_array = c.c_void_p() str_count = c.c_int() # 调用DLL函数 return_code = func(filename, name, result, c.byref(unmanaged_str_array), c.byref(str_count)) # 处理返回的字符串数组 str_array = c.cast(unmanaged_str_array, c.POINTER(c.c_char_p)) for i in range(str_count.value): # 根据DLL实际使用的编码调整decode参数,比如gbk、utf-16le等 print(str_array[i].decode('utf-8')) # 重要提醒:如果DLL为字符串数组分配了堆内存,一定要调用DLL提供的释放函数,避免内存泄漏!
额外注意事项:
- 如果
result是特定结构体的指针,你需要先用ctypes定义对应的结构体类,再创建结构体实例并传递其指针。 - 若DLL实际使用Unicode编码,把
c_char_p换成c_wchar_p,参数直接传Python字符串即可,不用转bytes。
内容的提问来源于stack exchange,提问作者ironykim
相关产品推荐
相关产品推荐

