Wie kann ich eine DLL-Datei aus Python verwenden?

186

Was ist der einfachste Weg, eine DLLDatei von innen zu verwenden Python?

Wie kann dies konkret durchgeführt werden, ohne zusätzlichen Wrapper- C++Code zu schreiben , dem die Funktionalität ausgesetzt werden soll Python?

Native PythonFunktionen werden der Verwendung einer Bibliothek eines Drittanbieters dringend vorgezogen.

Tom Hennen
quelle
@Remuze hast du die falsche Frage oder die falsche Antwort markiert? Sie sind beide Python, aber ich sehe keinen Grund, warum Sie sie überhaupt ähnlich finden würden (und ich habe den Revisionsverlauf überprüft, um sicherzustellen, dass er irgendwann in der Vergangenheit nicht näher kam)
Foon
@foon hmmm ja sorry, ich wollte eine andere Frage als Duplikat markieren und diese stellen :) Ich denke, das zeigt, wie ähnlich sie sind!
Trev Davies

Antworten:

153

Zur Vereinfachung der Verwendung ist ctypes der richtige Weg.

Das folgende Beispiel für ctypes stammt aus dem von mir geschriebenen Code (in Python 2.5). Dies war bei weitem der einfachste Weg, den ich gefunden habe, um das zu tun, was Sie verlangen.

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))

Das ctypesMaterial verfügt über alle Typen - C-Datentypen ( int, char, short, void*, und so weiter) , und durch den Wert oder Bezug passieren kann. Es kann auch bestimmte Datentypen zurückgeben, obwohl mein Beispiel dies nicht tut (die HLL-API gibt Werte zurück, indem eine als Referenz übergebene Variable geändert wird).


In Bezug auf das oben gezeigte spezifische Beispiel ist die EHLLAPI von IBM eine ziemlich konsistente Schnittstelle.

Alle Aufrufe übergeben vier ungültige Zeiger (EHLLAPI sendet den Rückkehrcode über den vierten Parameter zurück, einen Zeiger auf einen intso, während ich intals Rückgabetyp spezifiziere , kann ich ihn sicher ignorieren) gemäß der Dokumentation von IBM hier . Mit anderen Worten wäre die C-Variante der Funktion:

int hllApi (void *p1, void *p2, void *p3, void *p4)

Dies führt zu einer einzigen, einfachen ctypesFunktion, die alles kann, was die EHLLAPI-Bibliothek bietet. Es ist jedoch wahrscheinlich, dass andere Bibliotheken eine separate ctypesFunktion benötigen , die pro Bibliotheksfunktion eingerichtet wird.

Der Rückgabewert von WINFUNCTYPEist ein Funktionsprototyp, Sie müssen jedoch noch weitere Parameterinformationen einrichten (über die Typen hinaus). Jedes Tupel in hllApiParamshat einen Parameter "Richtung" (1 = Eingabe, 2 = Ausgabe usw.), einen Parameternamen und einen Standardwert - ctypesEinzelheiten finden Sie im Dokument

Sobald Sie die Prototyp- und Parameterinformationen haben, können Sie einen Python "aufrufbar" erstellen, hllApimit dem Sie die Funktion aufrufen können. Sie legen einfach die benötigte Variable ( p1durch p4in meinem Fall) und mit ihnen die Funktion aufrufen.

paxdiablo
quelle
1
Hallo, es mag lange her sein, dass hier jemand geantwortet hat, aber ich wollte etwas wissen, damit dies genau für mein Programm funktioniert. Können Sie mir sagen, was "HLLAPI" darin ist? Wenn ich auf meine DLL mit der Funktion "void BoxProperties (double L, double H, double W, double & A, double & V)" zugreifen möchte; Können Sie mir vorschlagen, welche Änderungen ich am obigen Code vornehmen soll, damit er funktioniert? Prost.
Neophile
4
Was genau macht hllApiParamsdas? Was ist der Sinn dieser Tupel? Es ist schwierig, einige der Dinge in diesem Beispiel mit der Dokumentation abzugleichen.
Jonathon Reinhart
1
@ JonathonReinhart, ich habe das spezifische Beispiel ein wenig mit etwas Text unten ausgearbeitet. Hoffentlich erklärt das das etwas besser. Wenn nicht, lass es mich wissen und ich werde es erneut versuchen :-)
paxdiablo
1
ausgezeichnete Antwort, hilft 6 Jahre später sehr :) Ich hätte eine +100 gesetzt, wenn ich es hätte tun können!
Oberst Beauvel
1
Dies ist aus Sicht der Newcomer von ctypes sehr verwirrend. Ich bin mir nicht ganz sicher, was los ist, selbst mit der Erklärung.
DuckPuncher
69

Diese Seite enthält ein sehr einfaches Beispiel für das Aufrufen von Funktionen aus einer DLL-Datei.

Der Vollständigkeit halber die Details hier umschreiben:

Es ist sehr einfach, eine DLL-Funktion in Python aufzurufen. Ich habe eine selbst erstellte DLL-Datei mit zwei Funktionen: addund subdie zwei Argumente annehmen.

add(a, b)
sub(a, b)Gibt die Addition von zwei Zahlen zurück. Gibt die Subtraktion von zwei Zahlen zurück

Der Name der DLL-Datei lautet "demo.dll".

Programm:

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

Ausgabe:

Addition value:11
Substraction:9

atul
quelle
2
Der Link in dieser Antwort ist defekt.
Kaliber64
10
Wenn der Link für Sie nicht funktioniert, machen Sie sich keine Sorgen, es ist ein direktes Kopieren und Einfügen. Sie vermissen keine Informationen.
Sumpf
6

Vielleicht mit Dispatch:

from win32com.client import Dispatch

zk = Dispatch("zkemkeeper.ZKEM") 

Wo zkemkeeper eine registrierte DLL-Datei auf dem System ist ... Danach können Sie auf Funktionen zugreifen, indem Sie sie einfach aufrufen:

zk.Connect_Net(IP_address, port)
Carlos Gomez
quelle
Ich arbeite an diesem zkemkeeper.ZKEM. Wissen Sie, wie ich Echtzeitereignisse in Python abrufen kann?
Sam Ziggler
4

Erstellen einer DLL und Verknüpfen unter Python mit ctypes

Ich stelle ein voll gearbeitet Beispiel dafür, wie ein Gebäude shared libraryund deren Verwendung unter Pythonmittels ctypes. Ich betrachte den WindowsFall und beschäftige mich damit DLLs. Es sind zwei Schritte erforderlich:

  1. Erstellen Sie die DLL mit dem Visual Studio-Compiler entweder über die Befehlszeile oder über die IDE.
  2. Verknüpfen Sie die DLL unter Python mit ctypes.

Die gemeinsam genutzte Bibliothek

Das, was shared libraryich betrachte, ist das Folgende und ist in der testDLL.cppDatei enthalten. Die einzige Funktion testDLLempfängt nur eine intund druckt sie aus.

#include <stdio.h>

extern "C" {

__declspec(dllexport)

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

} // extern "C"

Erstellen der DLL über die Befehlszeile

Um ein DLLWith Visual Studioüber die Befehlszeile zu erstellen , führen Sie es aus

"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\vsdevcmd"

um den Include-Pfad festzulegen und dann auszuführen

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

um die DLL zu erstellen.

Erstellen der DLLaus der IDE

Alternativ DLLkann das Visual Studiowie folgt erstellt werden:

  1. Datei -> Neu -> Projekt;
  2. Installiert -> Vorlagen -> Visual C ++ -> Windows -> Win32 -> Win32Project;
  3. Nächster;
  4. Anwendungstyp -> DLL;
  5. Zusätzliche Optionen -> Projekt leeren (auswählen);
  6. Zusätzliche Optionen -> Vorkompilierter Header (nicht auswählen);
  7. Projekt -> Eigenschaften -> Konfigurationsmanager -> Aktive Lösungsplattform: x64;
  8. Projekt -> Eigenschaften -> Konfigurationsmanager -> Aktive Lösungskonfiguration: Release.

Verknüpfen der DLL unter Python

Gehen Sie unter Python wie folgt vor

import os
import sys
from ctypes import *

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

lib.testDLL(3)
JackOLantern
quelle
Was ist, wenn die DLL in einem Python-Paket? Wie greife ich darauf zu?
Decadenza
3

ctypes ist am einfachsten zu verwenden, aber wenn Sie es (falsch) verwenden, kann Python abstürzen. Wenn Sie versuchen, schnell etwas zu tun, und Sie vorsichtig sind, ist es großartig.

Ich würde Sie ermutigen, sich Boost Python anzuschauen . Ja, es erfordert, dass Sie C ++ - Code schreiben und einen C ++ - Compiler haben, aber Sie müssen C ++ nicht wirklich lernen, um ihn zu verwenden, und Sie können einen kostenlosen (wie in Bier) C ++ - Compiler von Microsoft erhalten .

David Nehme
quelle
0

Wenn die DLL vom Typ COM-Bibliothek ist, können Sie Pythonnet verwenden.

pip install pythonnet

Versuchen Sie dann in Ihrem Python-Code Folgendes

import clr
clr.AddReference('path_to_your_dll')

Instanziieren Sie dann ein Objekt gemäß der Klasse in der DLL und greifen Sie auf die darin enthaltenen Methoden zu.

sattva_venu
quelle