DLL و Python

DLL و Python


صورة


لقد كنت مهتمًا مؤخرًا بموضوع استخدام DLLs من Python. بالإضافة إلى ذلك ، كان من المثير للاهتمام فهم هيكلها ، في حال اضطررت إلى تغيير مصدر المكتبات. بعد دراسة الموارد والأمثلة المختلفة حول هذا الموضوع ، أصبح من الواضح أن استخدام المكتبات الديناميكية يمكن أن يوسع بشكل كبير من قدرات Python. تم تحقيق أهدافي الخاصة ، ولكي لا تُنسى التجربة ، قررت أن ألخص في شكل مقال - لبناء معرفتي ومصادر مفيدة ، وفي نفس الوقت لفهم هذا الموضوع بشكل أفضل.


تحت الخفض ، ستجد مقالًا يحتوي على أمثلة ومصادر وتفسيرات مختلفة لها.


المحتوى


  • هيكل DLL
  • DLL و Python
    • اتصال DLL
    • أنواع البيانات في C و Python
    • دالة الوسيطات وقيم الإرجاع
    • امتلاك DLL واستخدامه
  • روابط مفيدة:

, .


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