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:
- 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
lib.printf(b"From dll with love!\n")
var_a = 31
lib.printf(b"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")
lib_2 = CDLL(r"C:\Windows\System32\msvcrt.dll")
var_a = 31
lib_2.printf(b"Print int_a = %d\n", var_a)
, 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")
print_from_C(b"Print int_c = %d\n", var_c)
:
Print int_c = 51
, . , DLL . , , . , , .
Python
ctypes
. .
1 — Python C, ctypes
.
, — , ? , , printf() :
:
from ctypes import *
lib = CDLL(r"C:\Windows\System32\msvcrt.dll")
printf = lib.printf
int_var = c_int(17)
printf(b"int_var = %d\n", int_var)
str_ = b"Hello, World\n"
str_pt = c_char_p(str_)
printf(str_pt)
print(str_pt)
print(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);
Python:
from ctypes import *
libc = CDLL(r"C:\Windows\System32\msvcrt.dll")
strcat = libc.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 :
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);
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;
}
Python:
from ctypes import *
lib_dll = cdll.LoadLibrary("DLL_example.dll")
str_ = b'Hello, Habr!'
p_str = c_char_p(str_)
lib_dll.SomeFunction(p_str)
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
Passport : . , , .
DLL :
main.c
#include "main.h"
#define SIZE_BUF 20
struct 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;
}
DLL_PROCESS_ATTACH
. DllMain
:
GetPassport — passport
.
*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):
_fields_ = [("name", c_char_p),
("surname", c_char_p),
("var", c_int)]
lib_dll = cdll.LoadLibrary("DLL_example.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)
lib_dll.SetPassport(pointer(passport))
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. . - — , — . , !
: