Come posso usare un file DLL da Python?


186

Qual è il modo più semplice per utilizzare un DLLfile dall'interno Python?

In particolare, come è possibile farlo senza scrivere alcun C++codice wrapper aggiuntivo per esporre la funzionalità Python?

La Pythonfunzionalità nativa è fortemente preferita rispetto all'utilizzo di una libreria di terze parti.


@Remuze hai taggato la domanda sbagliata o taggato con la risposta sbagliata? Sono entrambi in pitone, ma non vedo alcun motivo per cui li troveresti affatto simili (e ho controllato la cronologia delle revisioni per assicurarmi che non fosse in qualche modo più vicino ad un certo punto in passato)
Foon

@foon hmmm sì scusa, intendevo contrassegnare un'altra domanda come duplicata e metterla questa :) Immagino che mostri quanto sono simili!
Trev Davies,

Risposte:


154

Per facilità d'uso, il tipo è la strada da percorrere.

Il seguente esempio di tipi è dal codice reale che ho scritto (in Python 2.5). Questo è stato di gran lunga il modo più semplice che ho trovato per fare ciò che chiedi.

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 ctypesroba ha tutti i tipi del C-tipo di dati ( int, char, short, void*, e così via) e può passare per valore o riferimento. Può anche restituire tipi di dati specifici anche se il mio esempio non lo fa (l'API HLL restituisce valori modificando una variabile passata per riferimento).


In termini dell'esempio specifico mostrato sopra, EHLLAPI di IBM è un'interfaccia abbastanza coerente.

Tutte le chiamate passano quattro puntatori nulli (EHLLAPI restituisce il codice di ritorno attraverso il quarto parametro, un puntatore a un intcosì, mentre specifico intcome tipo di ritorno, posso tranquillamente ignorarlo) secondo la documentazione di IBM qui . In altre parole, la variante C della funzione sarebbe:

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

Ciò rende possibile un'unica e semplice ctypesfunzione in grado di eseguire qualsiasi operazione fornita dalla libreria EHLLAPI, ma è probabile che altre librerie necessitino di una ctypesfunzione separata impostata per funzione di libreria.

Il valore restituito da WINFUNCTYPEè un prototipo di funzione ma è comunque necessario impostare più informazioni sui parametri (oltre ai tipi). Ogni tupla in hllApiParamsha un parametro "direction" (1 = input, 2 = output e così via), un nome parametro e un valore predefinito - vedi il ctypesdocumento per i dettagli

Una volta che hai le informazioni sul prototipo e sui parametri, puoi creare un "callable" Python hllApicon cui chiamare la funzione. Devi semplicemente creare la variabile necessaria ( p1attraverso p4nel mio caso) e chiamare la funzione con loro.


1
Ciao, potrebbe passare molto tempo da quando qualcuno ha risposto qui, ma volevo sapere qualcosa per farlo funzionare esattamente per il mio programma. Potresti dirmi cos'è "HLLAPI" in questo? Inoltre, se voglio accedere alla mia dll con una funzione "voPro BoxProperties (double L, double H, double W, double & A, double & V);" potresti suggerirmi quali modifiche dovrei apportare al codice sopra per farlo funzionare? Saluti.
Neophile,

4
Che cosa fa esattamente hllApiParams? Qual è il punto di quelle tuple? È difficile abbinare alcune delle cose di questo esempio con la documentazione.
Jonathon Reinhart,

1
@JonathonReinhart, ho perfezionato un po 'l'esempio specifico con del testo in fondo. Spero che questo lo spieghi un po 'meglio. In caso contrario, fammi sapere e riproverò :-)
paxdiablo il

1
risposta eccellente, aiuta molto 6 anni dopo :) Avrei messo un +100 se avessi potuto farlo!
Colonnello Beauvel,

1
Questo è molto confuso dal punto di vista dei nuovi arrivati. Non sono esattamente sicuro di cosa stia succedendo, anche con la spiegazione.
DuckPuncher

69

Questa pagina contiene un esempio molto semplice di chiamata di funzioni da un file DLL.

Parafrasando i dettagli qui per completezza:

È molto semplice chiamare una funzione DLL in Python. Ho un file DLL fatto in casa con due funzioni: adde subche accetta due argomenti.

add(a, b)restituisce l'aggiunta di due numeri
sub(a, b)restituisce la sottrazione di due numeri

Il nome del file DLL sarà "demo.dll"

Programma:

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

Produzione:

Addition value:11
Substraction:9


2
Il link in questa risposta è rotto.
Kaliber64,

10
Se il collegamento non funziona per te non ti preoccupare, si tratta di una copia diretta incolla. Non ti stai perdendo alcuna informazione.
palude


6

Forse con Dispatch:

from win32com.client import Dispatch

zk = Dispatch("zkemkeeper.ZKEM") 

Dove zkemkeeper è un file DLL registrato sul sistema ... Successivamente, puoi accedere alle funzioni semplicemente chiamandole:

zk.Connect_Net(IP_address, port)

Sto lavorando su questo zkemkeeper.ZKEM, sai come posso ottenere eventi in tempo reale in Python?
Sam Ziggler,

4

Costruire una DLL e collegarla sotto Python usando ctypes

Vi presento un esempio completo di come costruire un shared librarye usarlo Pythonper mezzo di ctypes. Considero il Windowscaso e mi occupo di DLLs. Sono necessari due passaggi:

  1. Compilare la DLL utilizzando il compilatore di Visual Studio dalla riga di comando o dall'IDE;
  2. Collega la DLL in Python usando ctypes.

La libreria condivisa

Quello shared libraryche considero è il seguente ed è contenuto nel testDLL.cppfile. L'unica funzione testDLLriceve appena un inte lo stampa.

#include <stdio.h>

extern "C" {

__declspec(dllexport)

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

} // extern "C"

Creazione della DLL dalla riga di comando

Per creare un DLLcon Visual Studiodalla riga di comando eseguire

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

per impostare il percorso di inclusione e quindi eseguire

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

per costruire la DLL.

Costruendo DLLdall'IDE

In alternativa, DLLpuò essere compilato usando Visual Studiocome segue:

  1. File -> Nuovo -> Progetto;
  2. Installato -> Modelli -> Visual C ++ -> Windows -> Win32 -> Win32Project;
  3. Il prossimo;
  4. Tipo di applicazione -> DLL;
  5. Opzioni aggiuntive -> Progetto vuoto (seleziona);
  6. Opzioni aggiuntive -> Intestazione precompilata (deseleziona);
  7. Progetto -> Proprietà -> Configuration Manager -> Piattaforma soluzione attiva: x64;
  8. Progetto -> Proprietà -> Gestione configurazione -> Configurazione soluzione attiva: Rilascio.

Collegamento della DLL in Python

Sotto Python, procedi come segue

import os
import sys
from ctypes import *

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

lib.testDLL(3)

Cosa succede se la DLL in un pacchetto python? Come accedo?
decadenza,

3

i ctypes saranno la cosa più semplice da usare ma (mis) usarlo rende Python soggetto a crash. Se stai provando a fare qualcosa velocemente e stai attento, è grandioso.

Ti incoraggio a dare un'occhiata a Boost Python . Sì, richiede di scrivere del codice C ++ e di avere un compilatore C ++, ma in realtà non è necessario imparare il C ++ per usarlo e puoi ottenere un compilatore C ++ gratuito (come nella birra) da Microsoft .


0

Se la DLL è di tipo libreria COM, è possibile utilizzare pythonnet.

pip install pythonnet

Quindi nel tuo codice Python, prova quanto segue

import clr
clr.AddReference('path_to_your_dll')

quindi creare un'istanza di un oggetto secondo la classe nella DLL e accedere ai metodi al suo interno.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.