Comment appeler la bibliothèque dll en python

爱喝马黛茶的安东尼
Libérer: 2019-06-25 17:36:12
original
26728 Les gens l'ont consulté

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.

Comment appeler la bibliothèque dll en python

Présentation de la bibliothèque ctypes

from ctypes import *
Copier après la connexion

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)
Copier après la connexion

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")
Copier après la connexion

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类的对象。*/
Copier après la connexion

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
Copier après la connexion

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
Copier après la connexion

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
Copier après la connexion

5. Gérer les types de structure en C

Pourquoi mentionner cela séparément Parce que c'est le plus gênant et le plus compliqué Pour déclarer une structure de type C en python, vous devez utiliser une classe, et cette classe doit hériter de Structure.



Exemple :

Le code Python est le suivant :


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
Copier après la connexion

Exemple 2 :

Cet exemple appelle la fonction createprocessA dans kernel32.dll pour démarrer un processus de bloc-notes.

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))
Copier après la connexion

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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal