DLL & Python

Baru-baru ini saya tertarik pada topik menggunakan DLL dari Python. Selain itu, menarik untuk memahami strukturnya, jika Anda harus mengubah sumber perpustakaan. Setelah mempelajari berbagai sumber dan contoh tentang topik ini, menjadi jelas bahwa penggunaan perpustakaan dinamis dapat sangat memperluas kemampuan Python. Tujuan saya tercapai, dan agar pengalaman itu tidak dilupakan, saya memutuskan untuk merangkum dalam bentuk artikel - untuk menyusun pengetahuan dan sumber-sumber yang berguna, dan pada saat yang sama untuk lebih memahami topik ini.
Di bawah potongan Anda akan menemukan artikel dengan berbagai contoh, sumber, dan penjelasan untuk mereka.
Kandungan
- Struktur DLL
- DLL & Python
- Koneksi DLL
- Tipe Data dalam C dan Python
- Fungsi argumen dan mengembalikan nilai
- DLL sendiri dan penggunaannya
- Tautan yang bermanfaat:
, .
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. . - — , — . , !
: