Dans certains cas, C est nécessaire pour compléter l'efficacité de Python. Dans les applications pratiques, une certaine interaction de données est requise. En utilisant le module ctypes en Python, vous pouvez facilement appeler des dll Windows (y compris des fichiers sous Linux). Ce module sera expliqué en détail ci-dessous (en prenant la plateforme Windows comme exemple. Bien sûr, je suppose que vous savez déjà comment le faire). écrire sous Windows. Une DLL ne pose aucun problème.
Présentation de la bibliothèque ctypes
from ctypes import *
Supposons que vous ayez déjà une DLL (nommée add.dll) et que la DLL ait un cdecl (ici la convention d'appel est souligné car les fonctions d'exportation déclarées par la convention d'appel stdcall et la convention d'appel cdecl utilisent des fonctions de chargement différentes lors du chargement à l'aide de python, ce qui sera expliqué plus tard) La fonction d'exportation Add de la convention d'appel est ajoutée.
Recommandations associées : "Tutoriel vidéo Python"
Créer un fichier Python Test DllCall.py :
from ctypes import * dll = CDLL("add.dll") print dll.Add(1, 102)
Résultat : 103
Ce qui précède est un exemple simple. Parlons brièvement du processus d'appel :
1. Chargement de la DLL
Comme mentionné ci-dessus, lors du chargement, vous devez vous baser sur la convention d'appel à laquelle la fonction que vous êtes sur le point d'appeler se conforme.
Convention d'appel stdcall : deux méthodes de chargement
Objdll = ctypes.windll.LoadLibrary("dllpath") Objdll = ctypes.WinDLL("dllpath")
Convention d'appel cdecl : il existe également deux méthodes de chargement
Objdll = ctypes.cdll.LoadLibrary("dllpath") Objdll = ctypes.CDLL("dllpath") /*其实windll和cdll分别是WinDLL类和CDll类的对象。*/
2 Méthodes d'appel en dll
en 1 Lors du chargement. la dll, un objet DLL (en supposant que le nom est Objdll) sera renvoyé. Cet objet peut être utilisé pour appeler des méthodes dans la dll.
par exemple S'il y a une méthode nommée Add dans la dll (notez que si la méthode est déclarée par stdcall, si ce n'est pas une fonction exportée déclarée dans un fichier def ou extern "C", le compilateur modifiera le nom de la fonction. , veuillez faire attention à cela, je pense que vous comprenez. )
Appelez : nRet = Objdll.Add(12, 15) pour terminer un appel.
Il semble que l'appel soit très simple. Ne regardez pas seulement l'apparence. Haha, c'est parce que la fonction Add est trop simple. Supposons maintenant que la fonction nécessite que vous transmettiez un pointeur de type int (int*. ), vous pouvez utiliser byref dans le mot-clé library à implémenter, en supposant que le troisième paramètre de la fonction appelée est un pointeur de type int.
intPara = c_int(9) dll.sub(23, 102, byref(intPara)) print intPara.value
Si vous souhaitez transmettre un pointeur de tampon char et une longueur de tampon, il existe au moins quatre méthodes :
# 方法1 szPara = create_string_buffer('/0'*100) dll.PrintInfo(byref(szPara), 100); print szPara.value # 方法2 sBuf = 'aaaaaaaaaabbbbbbbbbbbbbb' pStr = c_char_p( ) pStr.value = sBuf #pVoid = ctypes.cast( pStr, ctypes.c_void_p ).value dll.PrintInfo(pStr, len(pStr.value)) print pStr.value # 方法3 strMa = "/0"*20 FunPrint = dll.PrintInfo FunPrint.argtypes = [c_char_p, c_int] #FunPrint.restypes = c_void_p nRst = FunPrint(strMa, len(strMa)) print strMa,len(strMa) # 方法4 pStr2 = c_char_p("/0") print pStr2.value #pVoid = ctypes.cast( pStr, ctypes.c_void_p ).value dll.PrintInfo(pStr2, len(pStr.value)) print pStr2.value
3 types de base C et tables de mappage de types implémentées dans ctypes
. CTYPES Type de données C Type de données
C_CHAR CHAR
C_SHORT Short
C_INT INT
C_LONG Long
C_ULONG UNSIGN Long
c_float Float
c_double 🎜> "_p", tel que int* est c_int_p, etc.
Pour implémenter la structure en langage C en python, vous devez utiliser des classes.
4. La fonction dans la DLL renvoie un pointeur.
Bien que ce ne soit pas une bonne méthode de programmation, la méthode de gestion de cette situation est également très simple. En fait, toutes les adresses sont renvoyées, convertissez-les dans le type python correspondant, puis accédez-y via l'attribut value.
pchar = dll.getbuffer() szbuffer = c_char_p(pchar) print szbuffer.value
Exemple :
def CreateGUID(): """ 创建一个全局唯一标识符 类似:E06093E2-699A-4BF2-A325-4F1EADB50E18 NewVersion """ try: # dll path strDllPath = sys.path[0] + str(os.sep) + "createguid.dll" dll = CDLL(strDllPath) b = dll.newGUID() a = c_char_p(b) except Exception, error: print error return "" return a.value
from ctypes import * # 定义_PROCESS_INFORMATION结构体 class _PROCESS_INFORMATION(Structure): _fields_ = [('hProcess', c_void_p), ('hThread', c_void_p), ('dwProcessId', c_ulong), ('dwThreadId', c_ulong)] # 定义_STARTUPINFO结构体 class _STARTUPINFO(Structure): _fields_ = [('cb',c_ulong), ('lpReserved', c_char_p), ('lpDesktop', c_char_p), ('lpTitle', c_char_p), ('dwX', c_ulong), ('dwY', c_ulong), ('dwXSize', c_ulong), ('dwYSize', c_ulong), ('dwXCountChars', c_ulong), ('dwYCountChars', c_ulong), ('dwFillAttribute', c_ulong), ('dwFlags', c_ulong), ('wShowWindow', c_ushort), ('cbReserved2', c_ushort), ('lpReserved2', c_char_p), ('hStdInput', c_ulong), ('hStdOutput', c_ulong), ('hStdError', c_ulong)] NORMAL_PRIORITY_CLASS = 0x00000020 #定义NORMAL_PRIORITY_CLASS kernel32 = windll.LoadLibrary("kernel32.dll") #加载kernel32.dll CreateProcess = kernel32.CreateProcessA #获得CreateProcess函数地址 ReadProcessMemory = kernel32.ReadProcessMemory #获得ReadProcessMemory函数地址 WriteProcessMemory = kernel32.WriteProcessMemory #获得WriteProcessMemory函数地址 TerminateProcess = kernel32.TerminateProcess # 声明结构体 ProcessInfo = _PROCESS_INFORMATION() StartupInfo = _STARTUPINFO() fileName = 'c:/windows/notepad.exe' # 要进行修改的文件 address = 0x0040103c # 要修改的内存地址 strbuf = c_char_p("_") # 缓冲区地址 bytesRead = c_ulong(0) # 读入的字节数 bufferSize = len(strbuf.value) # 缓冲区大小 # 创建进程 CreateProcess(fileName, 0, 0, 0, 0, NORMAL_PRIORITY_CLASS,0, 0, byref(StartupInfo), byref(ProcessInfo))
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!