“自己的懒惰,就是别人的进步”
要说难其实一点都不难,关键还是在数据类型转换上,比较恼人,像int,char之类的网上有好多示例,这里记录一下我遇到的麻烦:char*, char**的转换方式。为了更好的理解,我自己做了一个dll,来测试这一部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
#include <stdio.h> #include <stdlib.h> #include <string.h> #define O_SIZE 1024 #define DEBUG 0 #ifdef __cplusplus extern "C" { #endif int __declspec(dllexport) __stdcall pchar_ppchar_t(char* input,char** output) { if(DEBUG)fprintf(stderr,"DEBUG-%s\n",input); *output=(char*)malloc(O_SIZE); memset(*output,'\0',O_SIZE); memcpy(*output,input,strlen(input)); if(DEBUG)fprintf(stderr,"DEBUG-%s\n",*output); return 0; } int __declspec(dllexport) __stdcall pchar_pchar_t(char* input,char* output) { if(DEBUG)fprintf(stderr,"DEBUG-%s\n",input); memcpy(output,input,strlen(input)); if(DEBUG)fprintf(stderr,"DEBUG-%s\n",output); return 0; } #ifdef __cplusplus } #endif |
这是windows版本的,linux上只需要将“__declspec(dllexport) __stdcall”删除
然后是python调用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#http://stackoverflow.com/questions/4213095/python-and-ctypes-how-to-correctly-pass-pointer-to-pointer-into-dll from ctypes import * libc = windll.LoadLibrary("libpydll.dll") pchar_pchar_t = libc.pchar_pchar_t pchar_ppchar_t = libc.pchar_ppchar_t input = create_string_buffer(b"this is a sample") #print (input.value) #input = "this is a sample!" output = create_string_buffer(1024) result = pchar_pchar_t(input,output) if result == 0: print ("pchar_pchar_t output: %s" % output.value) else: print ("pchar_pchar_t: failed") output2 = POINTER(c_char)() output_s = "" result = pchar_ppchar_t(input, byref(output2)) if result != 0: print ("pchar_ppchar_t: failed") else: for i in range(1024): if output2[i] != b'\000': output_s += output2[i].decode('utf-8') print("pchar_ppchar_t output: %s" % output_s) |
这也是windows版本的,在linux下只需要将
libc = windll.LoadLibrary("libpydll.dll")
替换为
libc = cdll.LoadLibrary("libpydll.so")
然后将libpydll.so移到/usr/lib目录下
最主要的地方就是create_sring_buffer和POINTER(c_char)(),前者在官方ctypes说明里有,如果要输出字符串,就用这种方式;后者是在stackoverflow上找到的,提取output里面的字符串,虽然一个字符一个字符的连接也可以工作,但是我觉得这种办法很笨拙,不知道还有没有更好替代方式