DLL et Python

DLL et Python


image


Récemment, je me suis intéressé au sujet de l'utilisation des DLL de Python. De plus, il était intéressant de comprendre leur structure, au cas où vous deviez changer la source des bibliothèques. Après avoir étudié diverses ressources et exemples sur ce sujet, il est devenu clair que l'utilisation de bibliothèques dynamiques peut étendre considérablement les capacités de Python. Mes propres objectifs ont été atteints, et pour que l'expérience ne soit pas oubliée, j'ai décidé de résumer sous la forme d'un article - pour structurer mes connaissances et sources utiles, et en même temps pour mieux comprendre ce sujet.


Sous la coupe, vous trouverez un article avec divers exemples, sources et explications pour eux.


Contenu


  • Structure de DLL
  • DLL et Python
    • Connexion DLL
    • Types de données en C et Python
    • Fonction Arguments et valeurs de retour
    • DLL propre et son utilisation
  • Liens utiles:

, .


DLL


DLL — Dynamic Link Library — () Windows. , . .EXE — , DLL .


, , Microsoft: DLL?.




, , , .


DLL , -. . DllMain , DLL . .



1 — template, Code Blocks DLL.


1 , Code Blocks, DLL. :


#define DLL_EXPORT __declspec(dllexport) //   , 
                                         //                                                      // 
void DLL_EXPORT SomeFunction(const LPCSTR sometext); //    ,      

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) //  

DllMain. (fdwReason):


  • DLL_PROCESS_ATTACH – DLL. DLL . DllMain , - .


  • DLL_PROCESS_DETACH – DLL . DllMain .


  • DLL_THREAD_ATTACH – , DLL, . DLL - ? , .


  • DLL_THREAD_DETACH – , , DLL. "" ( ), .



, DLL , , .




DllMain , fdwReason , :


  • lpvReserved DLL:
    • 0 — .
    • 1 — .
  • hinstDLL DLL. EXE- DLL-, , .

: DLL.




1 SomeFunction, . , , __declspec(dllexport). , :


#define DLL_EXPORT __declspec(dllexport) 
void DLL_EXPORT SomeFunction(const LPCSTR sometext);

, , .


DLL & Python


, , DLL, , , , Code Blocks DLL.


DLL


Python , ctypes. ctypes , .


DLL, Python. :


  • cdll — , DLL . cdecl.
  • windll — stdcall. cdll.
  • oledll — stdcall , Windows HRESULT. WindowsError.

.


Windows DLL , — printf(). msvcrt.dll C:\WINDOWS\System32.


Python:


from ctypes import *

lib = cdll.msvcrt   #   msvcrt.dll
lib.printf(b"From dll with love!\n") #     printf

var_a = 31
lib.printf(b"Print int_a = %d\n", var_a) #   int 
                                # printf("Print int_a = %d\n", var_a); //   

:


From dll with love!
Print int_a = 31

windll oledll, , .


, dll. ctypes LoadLibrary. CDLL, cdll.LoadLibrary. , msvcrt.dll.


Python:


from ctypes import *

lib = cdll.LoadLibrary(r"C:\Windows\System32\msvcrt.dll")   
lib.printf(b"From dll with love!\n")    #     printf

lib_2 = CDLL(r"C:\Windows\System32\msvcrt.dll") #   msvcrt.dll

var_a = 31
lib_2.printf(b"Print int_a = %d\n", var_a)  #   int

, DLL, Python ""… . getattr(lib, attr_name). : , .


Python:


from ctypes import *

lib = cdll.LoadLibrary(r"C:\Windows\System32\msvcrt.dll")   

var_c = 51
print_from_C = getattr(lib, "printf")  # ,     "??2@YAPAXI@Z"
print_from_C(b"Print int_c = %d\n", var_c)

:


Print int_c = 51

, . , DLL . , , . , , .


Python


ctypes . .


types typeC typePython type
c_bool_Boolbool (1)
c_charchar1-character string
c_wcharwchar_t1-character unicode string
c_bytecharint/long
c_ubyteunsigned charint/long
c_shortshortint/long
c_ushortunsigned shortint/long
c_intintint/long
c_uintunsigned intint/long
c_longlongint/long
c_ulongunsigned longint/long
c_longlong__int64 or long longint/long
c_ulonglongunsigned __int64 or unsigned long longint/long
c_floatfloatfloat
c_doubledoublefloat
c_longdoublelong doublefloat
c_char_pchar * (NUL terminated)string or None
c_wchar_pwchar_t * (NUL terminated)unicode or None
c_void_pvoid *int/long or None

1 — Python C, ctypes.


, — , ? , , printf() :


:


from ctypes import *

lib = CDLL(r"C:\Windows\System32\msvcrt.dll")
printf = lib.printf #   printf()

int_var = c_int(17) #   int  C
printf(b"int_var = %d\n", int_var)

str_ = b"Hello, World\n" #   Python
str_pt = c_char_p(str_)  #   
printf(str_pt)           

print(str_pt)            
print(str_pt.value) # str_pt -   ,       value

:


int_var = 17
Hello, World
c_char_p(2814054827168)
b'Hello, World\n'

, ( , ) value, .



, int. restype. , argtypes.


, strcat . .


char *strcat (char *destination, const char *append); // C    ()  

Python:


from ctypes import *

libc = CDLL(r"C:\Windows\System32\msvcrt.dll")

strcat = libc.strcat        #    strcat
strcat.restype = c_char_p   # ,                                       # 
strcat.argtypes = [c_char_p, c_char_p] #    

str_1 = b"Hello,"
str_2 = b" Habr!"
str_pt = strcat(str_1, str_2) #   

print(str_pt)

:


b'Hello, Habr!'

DLL. DLL ctypes , .


DLL


1


DLL , , DLL , — DLL Python. Python x64, , DLL , DLL Python. , x64 Python x64, x32. , .


DLL, , , DllMain. , .


DLL :


// a sample exported function
void __declspec(dllexport) SomeFunction(const LPCSTR sometext)
{
    MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION);
}

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            printf("Load DLL in Python\n");

            printf("HINSTANCE = %p\n",hinstDLL); //    DLL

            if (lpvReserved)                     //   
              printf("DLL loaded with implicit layout\n"); 
            else
              printf("DLL loaded with explicit layout\n");          
            return 1;                            //  

        case DLL_PROCESS_DETACH:
            printf("DETACH DLL\n");
            break;

        case DLL_THREAD_ATTACH:
            break;

        case DLL_THREAD_DETACH:
            break;
    }
    return TRUE; // succesful
}

Python:


from ctypes import *

lib_dll = cdll.LoadLibrary("DLL_example.dll")   #   DLL
str_ = b'Hello, Habr!'
p_str = c_char_p(str_)                          #     str_
lib_dll.SomeFunction(p_str)                     #  SomeFunction  DLL

SomeFunction . .



2 — Code Blocks.


DLL_PROCESS_ATTACH, , Python :


lib_dll = cdll.LoadLibrary("DLL_example.dll")   #  


3 — DLL.


2


DLL Python, , . , Python. main.c, man.h main.py.


DLL :


main.h


#ifndef __MAIN_H__
#define __MAIN_H__

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>

#define DLL_EXPORT __declspec(dllexport) //   , 
                                         //                                                      // 
#ifdef __cplusplus
extern "C"
{
#endif

struct Passport{
    char*  name;
    char*  surname;
    int var;
};

void DLL_EXPORT SetName(char* new_name);
void DLL_EXPORT SetSurname(char* new_surname);
void DLL_EXPORT SetPassport(Passport* new_passport);
void DLL_EXPORT GetPassport(void);

#ifdef __cplusplus
}
#endif
#endif // __MAIN_H__

main.h Passport : . , , .


DLL :


main.c


#include "main.h"

#define SIZE_BUF 20

struct Passport passport; //   passport  Passport

//   
void DLL_EXPORT SetName(char* new_name)
{
    printf("SetName\n");
    strcpy(passport.name, new_name);
}

//   
void DLL_EXPORT SetSurname(char* new_surname)
{
    printf("SetSurname\n");
    strcpy(passport.surname, new_surname);
}

//    .
//      
void DLL_EXPORT SetPassport(Passport* new_passport)
{
    printf("SetPassport\n");
    strcpy(passport.name, new_passport->name);
    strcpy(passport.surname, new_passport->surname);
    passport.var = new_passport->var;
}

//     
void DLL_EXPORT GetPassport(void)
{
    printf("GetPassport: %s | %s | %d\n", passport.name, passport.surname, passport.var);
}

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            printf("Load DLL in Python\n");

            passport.name = (char*)malloc(SIZE_BUF * sizeof(char)); //  
            passport.surname = (char*)malloc(SIZE_BUF * sizeof(char)); //  

            passport.var = 17; //   
            SetName("Default"); //    
            SetSurname("Passport"); //    
            return 1;

        case DLL_PROCESS_DETACH:
            free (passport.name); //  
            free (passport.surname); //  
            printf("DETACH DLL\n");
            break;

        case DLL_THREAD_ATTACH:
            break;

        case DLL_THREAD_DETACH:
            break;
    }
    return TRUE; // succesful
}

DLL_PROCESS_ATTACH . DllMain :


  • GetPassportpassport .


  • *SetName(char new_name)** — name passport.


  • *SetSurname(char new_surname)** — surname passport.


  • *SetPassport(Passport new_passport)** — passport. .



Python.


Python


from ctypes import *

class Passport(Structure):              # ,    Passport 
    _fields_ = [("name", c_char_p),    #   main.h
                ("surname", c_char_p),
                ("var", c_int)]

lib_dll = cdll.LoadLibrary("DLL_example.dll")   #   DLL
lib_dll.SetPassport.argtypes  = [POINTER(Passport)] # ,   

lib_dll.GetPassport()          #    

lib_dll.SetName(c_char_p(b"Yury"))
lib_dll.SetSurname(c_char_p(b"Orlov"))

lib_dll.GetPassport()         #    

name = str.encode(("Vasiliy"))  #       
surname = c_char_p((b'Pupkin')) #       

passport = Passport(name, surname, 34) #    Passport

lib_dll.SetPassport(pointer(passport)) #      DLL

lib_dll.GetPassport()         #    

, , DLL Python DLL.


:


Load DLL in Python
SetName
SetSurname
GetPassport: Default | Passport | 17
SetName
SetSurname
GetPassport: Yury | Orlov | 17
SetPassport
GetPassport: Vasiliy | Pupkin | 34
DETACH DLL

P.S: , DLL Python. . - — , — . , !


:



All Articles