Como posso usar um arquivo DLL do Python?

186

Qual é a maneira mais fácil de usar um DLLarquivo de dentro Python?

Especificamente, como isso pode ser feito sem escrever nenhum C++código adicional para expor a funcionalidade Python?

A Pythonfuncionalidade nativa é fortemente preferida ao usar uma biblioteca de terceiros.

Tom Hennen
fonte
@Remuze, você marcou a pergunta errada ou a resposta errada? Eles são ambos python, mas não vejo nenhuma razão pela qual você gostaria de encontrar-los em tudo semelhante (e eu verifiquei o histórico de revisão para se certificar de que não era de alguma forma mais perto em algum momento no passado)
Foon
@ foon hmmm sim desculpe, eu pretendia sinalizar outra pergunta como duplicada e colocar essa :) Acho que isso mostra como elas são semelhantes!
precisa

Respostas:

154

Para facilitar o uso, ctypes é o caminho a percorrer.

O exemplo a seguir de ctypes é do código real que eu escrevi (no Python 2.5). Essa foi, de longe, a maneira mais fácil que encontrei para fazer o que você pede.

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

O ctypesmaterial tem a todos os tipos de dados do tipo C ( int, char, short, void*, e assim por diante) e pode passar por ou valor de referência. Ele também pode retornar tipos de dados específicos, embora meu exemplo não faça isso (a API da HLL retorna valores modificando uma variável passada por referência).


Em termos do exemplo específico mostrado acima, o EHLLAPI da IBM é uma interface bastante consistente.

Todas as chamadas passam por quatro ponteiros nulos (o EHLLAPI envia o código de retorno de volta pelo quarto parâmetro, um ponteiro para um intso, enquanto eu especifique intcomo o tipo de retorno, posso ignorá-lo com segurança) conforme a documentação da IBM aqui . Em outras palavras, a variante C da função seria:

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

Isso cria uma ctypesfunção única e simples capaz de fazer tudo o que a biblioteca EHLLAPI fornece, mas é provável que outras bibliotecas precisem de uma ctypesfunção separada configurada por função da biblioteca.

O valor de retorno de WINFUNCTYPEé um protótipo de função, mas você ainda precisa configurar mais informações de parâmetro (acima e acima dos tipos). Cada tupla hllApiParamspossui um parâmetro "direção" (1 = entrada, 2 = saída e assim por diante), um nome de parâmetro e um valor padrão - consulte o ctypesdocumento para obter detalhes

Depois de obter as informações de protótipo e parâmetro, você pode criar um Python "callable" hllApicom o qual chamar a função. Você simplesmente cria a variável necessária ( p1através p4do meu caso) e chama a função com eles.

paxdiablo
fonte
1
Olá, pode demorar muito tempo desde que alguém respondeu aqui, mas eu queria saber algo para fazer esse trabalho exatamente para o meu programa. Você poderia me dizer o que é "HLLAPI" nisso? Além disso, se eu quiser acessar minha dll com a função "void BoxProperties (double L, double H, double W, double & A, double & V);" você poderia me sugerir que alterações devo fazer no código acima para que ele funcione? Felicidades.
Neophile 9/09/11
4
O que exatamente faz hllApiParams? Qual é o sentido dessas tuplas? É difícil combinar algumas das coisas neste exemplo com a documentação.
Jonathon Reinhart
1
@ JonathonReinhart, detalhei um pouco o exemplo específico com algum texto na parte inferior. Felizmente, isso explica um pouco melhor. Caso contrário, avise-me e tentarei novamente :-)
paxdiablo
1
resposta excelente, ajuda bastante 6 anos depois :) Eu teria colocado um +100 se pudesse!
Coronel Beauvel
1
Isso é super confuso do ponto de vista dos novatos do ctypes. Não sei exatamente o que está acontecendo, mesmo com a explicação.
DuckPuncher
69

Esta página tem um exemplo muito simples de chamar funções de um arquivo DLL.

Parafraseando os detalhes aqui, para detalhes:

É muito fácil chamar uma função DLL no Python. Eu tenho um arquivo DLL self-made com duas funções:add e subque levam dois argumentos.

add(a, b)retorna adição de dois números
sub(a, b)retorna subtração de dois números

O nome do arquivo DLL será "demo.dll"

Programa:

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

Resultado:

Addition value:11
Substraction:9

atul
fonte
2
O link nesta resposta está quebrado.
Kaliber64
10
Se o link não funcionar para você, não se preocupe, é uma pasta de cópia direta. Você não está perdendo nenhuma informação.
pântano
6

Talvez com Dispatch:

from win32com.client import Dispatch

zk = Dispatch("zkemkeeper.ZKEM") 

Onde zkemkeeper é um arquivo DLL registrado no sistema ... Depois disso, você pode acessar as funções apenas chamando-as:

zk.Connect_Net(IP_address, port)
Carlos Gomez
fonte
Estou trabalhando neste zkemkeeper.ZKEM, você sabe como posso obter eventos em tempo real em python?
Sam Ziggler
4

Construindo uma DLL e vinculando-a no Python usando ctypes

Apresento um exemplo completo de como criar shared librarye usá-lo Pythonpor meio de ctypes. Eu considero o Windowscaso e trato DLLs. São necessárias duas etapas:

  1. Crie a DLL usando o compilador do Visual Studio na linha de comando ou no IDE;
  2. Vincule a DLL no Python usando ctypes.

A biblioteca compartilhada

O que shared libraryeu considero é o seguinte e está contido no testDLL.cpparquivo A única função testDLLapenas recebe inte imprime.

#include <stdio.h>

extern "C" {

__declspec(dllexport)

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

} // extern "C"

Criando a DLL a partir da linha de comando

Para criar um DLLcom a Visual Studiopartir da linha de comando, execute

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

para definir o caminho de inclusão e, em seguida, execute

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

para criar a DLL.

Construindo o DLL partir do IDE

Como alternativa, o DLLpode ser construído usando Visual Studioo seguinte:

  1. Arquivo -> Novo -> Projeto;
  2. Instalado -> Modelos -> Visual C ++ -> Windows -> Win32 -> Win32Project;
  3. Próximo;
  4. Tipo de aplicativo -> DLL;
  5. Opções adicionais -> Projeto vazio (selecione);
  6. Opções adicionais -> Cabeçalho pré-compilado (desmarcar);
  7. Projeto -> Propriedades -> Gerenciador de Configurações -> Plataforma de solução ativa: x64;
  8. Projeto -> Propriedades -> Gerenciador de Configurações -> Configuração da solução ativa: Release.

Vinculando a DLL no Python

Em Python, faça o seguinte

import os
import sys
from ctypes import *

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

lib.testDLL(3)
JackOLantern
fonte
E se a DLL em um pacote python? Como faço para acessá-lo?
decadenza 12/06
3

ctypes será a coisa mais fácil de usar, mas (mis) usá-lo torna o Python sujeito a falhas. Se você está tentando fazer algo rapidamente e tem cuidado, é ótimo.

Eu encorajo você a conferir o Boost Python . Sim, requer que você escreva algum código C ++ e tenha um compilador C ++, mas na verdade não precisa aprender C ++ para usá-lo, e pode obter um compilador C ++ gratuito (como em cerveja) da Microsoft .

David Nehme
fonte
0

Se a DLL for do tipo COM library, você poderá usar pythonnet.

pip install pythonnet

Em seguida, no seu código python, tente o seguinte

import clr
clr.AddReference('path_to_your_dll')

instancie um objeto conforme a classe na DLL e acesse os métodos nele.

sattva_venu
fonte