Comment puis-je utiliser un fichier DLL de Python?

186

Quelle est la manière la plus simple d'utiliser un DLLfichier de l'intérieurPython ?

Plus précisément, comment cela peut-il être fait sans écrire de C++code wrapper supplémentaire pour exposer la fonctionnalité Python?

La Pythonfonctionnalité native est fortement préférée à l'utilisation d'une bibliothèque tierce.

Tom Hennen
la source
@Remuze avez-vous tagué la mauvaise question ou la mauvaise réponse? Ils sont tous les deux python, mais je ne vois aucune raison pour laquelle vous les trouveriez similaires (et j'ai vérifié l'historique des révisions pour m'assurer qu'il n'était pas plus proche à un moment donné dans le passé)
Foon
@foon hmmm oui désolé, je voulais signaler une autre question en double et mettre celle-ci :) Je suppose que cela montre à quel point elles sont similaires!
Trev Davies

Réponses:

154

Pour la facilité d'utilisation, ctypes est la voie à suivre.

L'exemple suivant de ctypes provient du code que j'ai écrit (en Python 2.5). Cela a été, 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 ctypessubstance possède tous les types de données de type C ( int, char, short, void*, etc.) et peut passer de la valeur ou de référence. Il peut également renvoyer des types de données spécifiques bien que mon exemple ne le fasse pas (l'API HLL renvoie des valeurs en modifiant une variable passée par référence).


En termes de l'exemple spécifique montré ci-dessus, EHLLAPI d'IBM est une interface assez cohérente.

Tous les appels passent quatre pointeurs vides (EHLLAPI renvoie le code de retour via le quatrième paramètre, un pointeur vers un intso, alors que je spécifie intcomme type de retour, je peux l'ignorer en toute sécurité) selon la 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 en fait une ctypesfonction simple et unique capable de faire tout ce que la bibliothèque EHLLAPI fournit, mais il est probable que d'autres bibliothèques auront besoin d'une ctypesfonction distincte configurée par fonction de bibliothèque.

La valeur de retour de WINFUNCTYPEest un prototype de fonction, mais vous devez toujours configurer plus d'informations sur les paramètres (au-delà des types). Chaque tuple dans hllApiParamsa un paramètre "direction" (1 = entrée, 2 = sortie et ainsi de suite), un nom de paramètre et une valeur par défaut - voir le document ctypespour plus de détails

Une fois que vous avez le prototype et les informations de paramètre, vous pouvez créer un Python "appelable" hllApiavec lequel appeler la fonction. Vous créez simplement la variable nécessaire ( p1via p4dans mon cas) et appelez la fonction avec eux.

paxdiablo
la source
1
Bonjour, cela fait peut-être longtemps que quelqu'un n'a pas répondu ici mais je voulais savoir quelque chose pour que cela fonctionne exactement pour mon programme. Pourriez-vous me dire ce que signifie «HLLAPI» dans tout cela? Aussi, si je veux accéder à ma dll avec une fonction "void BoxProperties (double L, double H, double W, double & A, double & V);" pouvez-vous me suggérer les modifications à apporter au code ci-dessus pour le faire fonctionner? À votre santé.
Neophile
4
Que fait exactement hllApiParams? Quel est l'intérêt de ces tuples? Il est difficile de faire correspondre certaines des choses de cet exemple avec la documentation.
Jonathon Reinhart
1
@JonathonReinhart, j'ai un peu étoffé l'exemple spécifique avec du texte en bas. Espérons que cela explique un peu mieux. Sinon, faites-le moi savoir et j'essaierai à nouveau :-)
paxdiablo
1
excellente réponse, aide beaucoup 6 ans après :) J'aurais mis un +100 si j'avais pu le faire!
Colonel Beauvel
1
C'est super déroutant du point de vue des nouveaux arrivants de ctypes .. Je ne sais pas exactement ce qui se passe, même avec l'explication.
DuckPuncher
69

Cette page présente un exemple très simple d'appel de fonctions à partir d'un fichier DLL.

Paraphrasant les détails ici par souci d'exhaustivité:

Il est très facile d'appeler une fonction DLL en Python. J'ai un fichier DLL auto-créé avec deux fonctions: addet subqui prend deux arguments.

add(a, b)renvoie l'addition de deux nombres
sub(a, b)renvoie la soustraction de deux nombres

Le 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

Production:

Addition value:11
Substraction:9

atul
la source
2
Le lien dans cette réponse est rompu.
Kaliber64
10
Si le lien ne fonctionne pas pour vous, ne vous inquiétez pas, il s'agit d'un copier-coller direct. Vous ne manquez aucune information.
marsh
6

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)
Carlos Gomez
la source
Je travaille sur ce zkemkeeper.ZKEM, savez-vous comment je peux obtenir des événements en temps réel en python?
Sam Ziggler
4

Construire une DLL et la lier sous Python à l'aide de ctypes

Je présente un exemple entièrement travaillé sur la façon de construire un shared libraryet de l'utiliser Pythonau moyen de ctypes. Je considère le Windowscas et je traite DLLs. Deux étapes sont nécessaires:

  1. Générez la DLL à l'aide du compilateur de Visual Studio à partir de la ligne de commande ou de l'EDI;
  2. Liez la DLL sous Python à l'aide de ctypes.

La bibliothèque partagée

Le que shared libraryje considère est le suivant et est contenu dans le testDLL.cppdossier. La seule fonction testDLLreçoit juste un intet l'imprime.

#include <stdio.h>

extern "C" {

__declspec(dllexport)

void testDLL(const int i) {
    printf("%d\n", i);
}

} // extern "C"

Construire la DLL à partir de la ligne de commande

Pour créer un DLLavec à Visual Studiopartir 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, puis exécutez

cl.exe /D_USRDLL /D_WINDLL testDLL.cpp /MT /link /DLL /OUT:testDLL.dll

pour créer la DLL.

Construire le à DLLpartir de l'IDE

Alternativement, le DLLpeut être construit Visual Studiocomme suit:

  1. Fichier -> Nouveau -> Projet;
  2. Installé -> Modèles -> Visual C ++ -> Windows -> Win32 -> Win32Project;
  3. Prochain;
  4. Type d'application -> DLL;
  5. Options supplémentaires -> Projet vide (sélectionnez);
  6. Options supplémentaires -> En-tête précompilé (désélectionner);
  7. Projet -> Propriétés -> Configuration Manager -> Plateforme de solution active: x64;
  8. Projet -> Propriétés -> Configuration Manager -> Configuration de la solution active: Release.

Lier la DLL sous Python

Sous Python, procédez comme suit

import os
import sys
from ctypes import *

lib = cdll.LoadLibrary('testDLL.dll')

lib.testDLL(3)
Citrouille d'Halloween
la source
Et si la DLL dans un package python? Comment y accéder?
decadenza le
3

ctypes sera la chose la plus simple à utiliser mais (mal) l'utiliser rend Python sujet au 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 ayez un compilateur C ++, mais vous n'avez pas réellement besoin d'apprendre C ++ pour l'utiliser, et vous pouvez obtenir un compilateur C ++ gratuit (comme dans la bière) de Microsoft .

David Nehme
la source
0

Si la DLL est de type bibliothèque COM, vous pouvez utiliser pythonnet.

pip install pythonnet

Ensuite, dans votre code python, essayez ce qui suit

import clr
clr.AddReference('path_to_your_dll')

puis instanciez un objet selon la classe dans la DLL et accédez aux méthodes qu'il contient.

sattva_venu
la source