DLL & Python

Recently I was interested in the topic of using DLLs from Python. In addition, it was interesting to understand their structure, in case you have to change the source of the libraries. After studying various resources and examples on this topic, it became clear that the use of dynamic libraries can greatly expand the capabilities of Python. My own goals were achieved, and so that the experience was not forgotten, I decided to summarize in the form of an article - to structure my knowledge and useful sources, and at the same time to better understand this topic.
Under the cut you will find an article with various examples, sources and explanations for them.
Content
- DLL structure
- DLL & Python
- DLL connection
- Data Types in C and Python
- Arguments function and return values
- Own DLL and its use
- Useful links:
, .
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. . - — , — . , !
: