Home  >  Article  >  Backend Development  >  How to call dll library in python

How to call dll library in python

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

In some cases, C is needed to supplement efficiency in python. In practical applications, some data interaction is required. Using the ctypes module in Python, you can easily call Windows DLLs (including so files under Linux). This module will be explained in detail below (taking the Windows platform as an example). Of course, I assume that you already know how to write under Windows. A DLL is no problem.

How to call dll library in python

Introducing the ctypes library

from ctypes import *

Assume that you already have a DLL (the name is add.dll), and the DLL has a cdecl (here The calling convention is emphasized because the export functions declared by the stdcall calling convention and the cdecl calling convention use different loading functions when loading using python, which will be explained later) The export function Add of the calling convention is added.

Related recommendations: "python video tutorial"

Create a Python file DllCall.py test:

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

Result: 103

The above is a simple example. Let’s briefly talk about the calling process:
1. Loading DLL
As mentioned above, when loading, you should base on what calling convention the function you are about to call conforms to.
stdcall calling convention: two loading methods

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

cdecl calling convention: there are also two loading methods

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

2. Call the method in the dll

In 1 When loading the dll, a DLL object (assuming the name is Objdll) will be returned. This object can be used to call methods in the dll.

e.g. If there is a method named Add in the dll (note that if the method is declared by stdcall, if it is not an exported function declared in a def file or extern "C", the compiler will modify the function name. , please pay attention to this, I think you understand.)
Call: nRet = Objdll.Add(12, 15), which completes a call.
It seems that the call is very simple. Don’t just look at the appearance. Haha, this is because the Add function is too simple. Now assuming that the function requires you to pass in an int type pointer (int*), you can use byref in the library keyword to implement, assuming that the third parameter of the function being called is a pointer of type int.

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

If you want to pass in a char buffer pointer and buffer length, there are at least four methods:

# 方法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 basic types and type mapping tables implemented in ctypes
ctypes data type C data type
c_char char
c_short short
c_int int
c_long                                                                                                                                                                                                                                    ​                                                                                                                                                                                               . ##The corresponding pointer type is followed by "_p", such as int* is c_int_p, etc.
To implement the structure in c language in python, you need to use classes.
4. The function in the DLL returns a pointer.
Although this is not a good programming method, the method of handling this situation is also very simple. In fact, all the addresses are returned, convert them to the corresponding python type, and then access them through the value attribute.

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

5. Dealing with structure types in C
Why mention this separately? Because this is the most troublesome and complex. To declare a structure similar to c in python, you need to A class is used, and this class must inherit from Structure.

Example:

The Python code is as follows:

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

Example 2:

This example calls the createprocessA function in kernel32.dll to start a notepad process.

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

The above is the detailed content of How to call dll library in python. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn