Heim  >  Artikel  >  Backend-Entwicklung  >  So rufen Sie die DLL-Bibliothek in Python auf

So rufen Sie die DLL-Bibliothek in Python auf

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼Original
2019-06-13 11:51:1326752Durchsuche

In einigen Fällen ist C erforderlich, um die Effizienz in Python zu ergänzen. In praktischen Anwendungen ist eine gewisse Dateninteraktion erforderlich. Mithilfe des ctypes-Moduls in Python können Sie ganz einfach Windows-DLLs (einschließlich solcher Dateien unter Linux) aufrufen. Dieses Modul wird im Folgenden ausführlich erläutert (am Beispiel der Windows-Plattform gehe ich natürlich davon aus, dass Sie bereits wissen, wie das geht). Unter Windows schreiben ist kein Problem.

So rufen Sie die DLL-Bibliothek in Python auf

Einführung in die ctypes-Bibliothek

from ctypes import *

Angenommen, Sie haben bereits eine DLL (mit dem Namen add.dll) und die DLL hat ein cdecl (hier die Aufrufkonvention). wird hervorgehoben, da die von der stdcall-Aufrufkonvention und der cdecl-Aufrufkonvention deklarierten Exportfunktionen beim Laden mit Python unterschiedliche Ladefunktionen verwenden, was später erläutert wird.) Die Exportfunktion Add der Aufrufkonvention wurde hinzugefügt.

Verwandte Empfehlungen: „Python-Video-Tutorial

Erstellen Sie eine Python-Datei DllCall.py-Test:

from ctypes import *  
dll = CDLL("add.dll")  
print dll.Add(1, 102)

Ergebnis: 103

Das Obige ist ein einfaches Beispiel. Lassen Sie uns kurz über den Aufrufvorgang sprechen:
1. Laden der DLL
Wie oben erwähnt, sollten Sie sich beim Laden darauf stützen, welcher Aufrufkonvention die Funktion entspricht, die Sie aufrufen möchten.
stdcall-Aufrufkonvention: zwei Lademethoden

Objdll = ctypes.windll.LoadLibrary("dllpath")  
Objdll = ctypes.WinDLL("dllpath")

cdecl-Aufrufkonvention: Es gibt auch zwei Lademethoden

Objdll = ctypes.cdll.LoadLibrary("dllpath")  
Objdll = ctypes.CDLL("dllpath")  
/*其实windll和cdll分别是WinDLL类和CDll类的对象。*/

2. Aufrufmethoden in DLL

in 1 Beim Laden In der DLL wird ein DLL-Objekt zurückgegeben (vorausgesetzt, der Name lautet Objdll). Dieses Objekt kann zum Aufrufen von Methoden in der DLL verwendet werden.

z.B. Wenn es eine Methode namens Add in der DLL gibt (beachten Sie, dass der Compiler Änderungen vornimmt, wenn die Methode durch stdcall deklariert wird, es sich nicht um eine exportierte Funktion handelt, die in einer Def-Datei oder extern „C“ deklariert ist). Bitte achten Sie darauf, ich denke, Sie verstehen )
Rufen Sie auf: nRet = Objdll.Add(12, 15) um einen Aufruf abzuschließen.
Es scheint, dass der Aufruf sehr einfach ist. Schauen Sie sich nicht nur das Aussehen an, das liegt daran, dass die Funktion „Add“ zu einfach ist. ), können Sie zur Implementierung byref im Bibliotheksschlüsselwort verwenden, vorausgesetzt, der dritte Parameter der aufgerufenen Funktion ist ein Zeiger vom Typ int.

intPara = c_int(9)  
dll.sub(23, 102, byref(intPara))  
print intPara.value

Wenn Sie einen Zeichenpufferzeiger und eine Pufferlänge übergeben möchten, gibt es mindestens vier Methoden:

# 方法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. C-Basistypen und Typzuordnungstabellen, die in ctypes implementiert sind
ctypes Datentyp C Datentyp
c_char char
c_short short
c_int int
c_long long
c_ulong unsign long
c_float float.
c_double                                                                                                                                                                                                                                                   🎜>Der entsprechende. Zeiger Typ wird mit angehängt „_p“, wie int* ist c_int_p usw.
Um die Struktur in C-Sprache in Python zu implementieren, müssen Sie Klassen verwenden.
4. Die Funktion in der DLL gibt einen Zeiger zurück.
Obwohl dies keine gute Programmiermethode ist, ist die Methode zur Handhabung dieser Situation auch sehr einfach. Tatsächlich werden alle Adressen zurückgegeben, in den entsprechenden Python-Typ konvertiert und dann über das Wertattribut darauf zugegriffen.

pchar = dll.getbuffer()  szbuffer = c_char_p(pchar)  print szbuffer.value

5. Warum dies separat erwähnen? Um eine C-ähnliche Struktur in Python zu deklarieren, muss eine Klasse verwendet werden Diese Klasse muss von Structure erben.


Beispiel:
Der Python-Code lautet wie folgt:

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

Beispiel 2:
Dieses Beispiel ruft die Funktion createprocessA in kernel32.dll auf, um eine zu starten Notizblock-Prozess.

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))

Das obige ist der detaillierte Inhalt vonSo rufen Sie die DLL-Bibliothek in Python auf. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn