Quel est le moyen le plus simple d’utiliser un fichier DLL
à partir de Python
?
Plus précisément, comment cela peut-il être fait sans écrire du code additionnel C++
pour emballer afin d'exposer la fonctionnalité à Python
?
La fonctionnalité native Python
est fortement préférable à l'utilisation d'une bibliothèque tierce.
Pour plus de facilité, ctypes est la voie à suivre.
L'exemple suivant de ctypes provient du code que j'ai écrit (dans Python 2.5). C'est de loin le moyen le plus simple que j'ai trouvé pour faire ce que vous demandez.
import ctypes
# Load DLL into memory.
hllDll = ctypes.WinDLL ("c:\\PComm\\ehlapi32.dll")
# Set up prototype and parameters for the desired function call.
# HLLAPI
hllApiProto = ctypes.WINFUNCTYPE (
ctypes.c_int, # Return type.
ctypes.c_void_p, # Parameters 1 ...
ctypes.c_void_p,
ctypes.c_void_p,
ctypes.c_void_p) # ... thru 4.
hllApiParams = (1, "p1", 0), (1, "p2", 0), (1, "p3",0), (1, "p4",0),
# Actually map the call ("HLLAPI(...)") to a Python name.
hllApi = hllApiProto (("HLLAPI", hllDll), hllApiParams)
# This is how you can actually call the DLL function.
# Set up the variables and call the Python name with them.
p1 = ctypes.c_int (1)
p2 = ctypes.c_char_p (sessionVar)
p3 = ctypes.c_int (1)
p4 = ctypes.c_int (0)
hllApi (ctypes.byref (p1), p2, ctypes.byref (p3), ctypes.byref (p4))
La substance ctypes
a tous les types de données de type C (int
, char
, short
, void*
, etc.) et peut passer par valeur ou référence. Elle peut également renvoyer des types de données spécifiques, mais mon exemple ne le fait pas (l'API HLL renvoie des valeurs en modifiant une variable passée par référence).
En ce qui concerne l'exemple spécifique présenté ci-dessus, l'interface EHLLAPI d'IBM est une interface relativement cohérente.
Tous les appels transmettent quatre pointeurs vides (EHLLAPI renvoie le code de retour via le quatrième paramètre, un pointeur sur un int
, de sorte que, si je spécifie int
comme type de retour, je peux l'ignorer en toute sécurité) conformément à Documentation d'IBM ici . En d'autres termes, la variante C de la fonction serait:
int hllApi (void *p1, void *p2, void *p3, void *p4)
Cela donne une fonction simple et simple ctypes
capable de faire tout ce que la bibliothèque EHLLAPI fournit, mais il est probable que d'autres bibliothèques auront besoin d'une fonction ctypes
distincte configurée par fonction de bibliothèque.
La valeur de retour de WINFUNCTYPE
est un prototype de fonction, mais vous devez toujours configurer plus d'informations sur les paramètres (en plus des types). Chaque Tuple dans hllApiParams
a un paramètre "direction" (1 = entrée, 2 = sortie, etc.), un nom de paramètre et une valeur par défaut - voir le doco ctypes
pour plus de détails
Une fois que vous avez les informations relatives au prototype et aux paramètres, vous pouvez créer un Python "appelable" hllApi
avec lequel appeler la fonction. Vous créez simplement la variable nécessaire (p1
à p4
dans mon cas) et appelez la fonction avec eux.
Cette page présente un exemple très simple d’appel de fonctions à partir d’un fichier DLL.
Paraphrasant les détails ici pour plus de détails:
Il est très facile d'appeler une fonction DLL en Python. J'ai un fichier DLL créé de manière autonome avec deux fonctions:
add
etsub
qui prennent deux arguments.
add(a, b)
retourne l'ajout de deux nombressub(a, b)
renvoie la soustraction de deux nombresLe nom du fichier DLL sera "demo.dll"
Programme:
from ctypes import*
# give location of dll
mydll = cdll.LoadLibrary("C:\\demo.dll")
result1= mydll.add(10,1)
result2= mydll.sub(10,1)
print "Addition value:"+result1
print "Substraction:"+result2
Sortie:
Addition value:11
Substraction:9
ctypes peut être utilisé pour accéder aux dll, voici un tutoriel:
Peut-être avec Dispatch
:
from win32com.client import Dispatch
zk = Dispatch("zkemkeeper.ZKEM")
Où zkemkeeper est un fichier DLL enregistré sur le système ... Après cela, vous pouvez accéder aux fonctions simplement en les appelant:
zk.Connect_Net(IP_address, port)
ctypes sera la chose la plus facile à utiliser, mais son utilisation (mal) rend Python sujet à un crash. Si vous essayez de faire quelque chose rapidement et que vous faites attention, c'est génial.
Je vous encourage à consulter Boost Python . Oui, cela nécessite que vous écriviez du code C++ et que vous disposiez d'un compilateur C++, mais vous n'avez pas besoin d'apprendre le C++ pour l'utiliser, et vous pouvez en obtenir un gratuitement (comme dans beer) Compilateur C++ de Microsoft .
Je présente un exemple complet sur la manière de construire un shared library
et de l’utiliser sous Python
au moyen de ctypes
. Je considère le cas Windows
et traite DLLs
. Deux étapes sont nécessaires:
Le shared library
que j'estime est le suivant et est contenu dans le fichier testDLL.cpp
. La seule fonction testDLL
reçoit juste un int
et l’imprime.
#include <stdio.h>
extern "C" {
__declspec(dllexport)
void testDLL(const int i) {
printf("%d\n", i);
}
} // extern "C"
Pour construire une DLL
avec Visual Studio
à partir de la ligne de commande, exécutez
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\vsdevcmd"
pour définir le chemin d'inclusion et ensuite exécuter
cl.exe /D_USRDLL /D_WINDLL testDLL.cpp /MT /link /DLL /OUT:testDLL.dll
pour construire la DLL.
DLL
à partir de l'IDESinon, la DLL
peut être construite en utilisant Visual Studio
comme suit:
Sous Python, procédez comme suit
import os
import sys
from ctypes import *
lib = cdll.LoadLibrary('testDLL.dll')
lib.testDLL(3)