Bagaimana saya bisa menggunakan file DLL dari Python?

186

Apa cara termudah untuk menggunakan DLLfile dari dalam Python?

Secara khusus, bagaimana ini bisa dilakukan tanpa menulis C++kode pembungkus tambahan untuk mengekspos fungsionalitas Python?

PythonFungsi asli sangat disukai daripada menggunakan perpustakaan pihak ketiga.

Tom Hennen
sumber
@Remuze apakah Anda menandai pertanyaan yang salah atau menandai dengan jawaban yang salah? Mereka berdua python, tapi saya tidak melihat alasan mengapa Anda akan menemukan mereka sama (dan saya memeriksa riwayat revisi untuk memastikan itu entah bagaimana lebih dekat di beberapa titik di masa lalu)
Foon
@ tolong hmmm ya maaf, saya bermaksud menandai pertanyaan lain sebagai duplikat dan letakkan yang ini :) Saya kira itu menunjukkan betapa miripnya mereka!
Trev Davies

Jawaban:

154

Untuk kemudahan penggunaan, ctypes adalah cara yang harus dilakukan.

Contoh ctypes berikut ini dari kode aktual yang saya tulis (dengan Python 2.5). Sejauh ini, ini adalah cara termudah yang saya temukan untuk melakukan apa yang Anda minta.

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

The ctypeshal memiliki semua jenis C-tipe data ( int, char, short, void*, dan sebagainya) dan dapat lulus dengan nilai atau referensi. Itu juga dapat mengembalikan tipe data tertentu meskipun contoh saya tidak melakukan itu (API HLL mengembalikan nilai dengan memodifikasi variabel yang dikirimkan oleh referensi).


Dalam hal contoh spesifik yang ditunjukkan di atas, EHLLAPI IBM adalah antarmuka yang cukup konsisten.

Semua panggilan melewati empat void pointer (EHLLAPI mengirimkan kembali kode melalui parameter keempat, sebuah penunjuk ke intjadi, sementara saya tentukan intsebagai tipe pengembalian, saya dapat dengan aman mengabaikannya) sesuai dokumentasi IBM di sini . Dengan kata lain, varian C dari fungsi tersebut adalah:

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

Ini membuat ctypesfungsi tunggal yang sederhana dapat melakukan apa saja yang disediakan oleh perpustakaan EHLLAPI, tetapi kemungkinan perpustakaan lain akan membutuhkan ctypesfungsi terpisah yang diatur per fungsi perpustakaan.

Nilai kembali dari WINFUNCTYPEadalah prototipe fungsi tetapi Anda masih harus mengatur informasi parameter lebih banyak (lebih dan di atas jenis). Setiap tuple dalam hllApiParamsmemiliki "arah" parameter (1 = input, 2 = output dan sebagainya), nama parameter dan nilai default - lihat dokumen ctypesuntuk detail

Setelah Anda memiliki prototipe dan informasi parameter, Anda dapat membuat Python "callable" hllApiuntuk memanggil fungsi tersebut. Anda cukup membuat variabel yang diperlukan ( p1melalui p4dalam kasus saya) dan memanggil fungsi dengan mereka.

paxdiablo
sumber
1
Halo, mungkin sudah lama sejak seseorang menjawab di sini, tetapi saya ingin tahu sesuatu untuk membuat ini berfungsi tepat untuk program saya. Bisakah Anda memberi tahu saya apa "HLLAPI" dalam hal ini? Juga, jika saya ingin mengakses dll saya dengan fungsi "void BoxProperties (double L, double H, double W, double & A, double & V);" dapatkah Anda memberi tahu saya perubahan apa yang harus saya lakukan pada kode di atas untuk membuatnya berfungsi? Bersulang.
Neophile
4
Apa yang sebenarnya hllApiParamsdilakukan? Apa gunanya tupel itu? Sulit untuk mencocokkan beberapa hal dalam contoh ini dengan dokumentasi.
Jonathon Reinhart
1
@ JonathonReinhart, saya telah menyempurnakan contoh spesifik sedikit dengan beberapa teks di bagian bawah. Semoga itu menjelaskannya sedikit lebih baik. Jika tidak, beri tahu saya dan saya akan mencoba lagi :-)
paxdiablo
1
jawaban yang sangat baik, banyak membantu 6 tahun setelah :) Saya akan meletakkan +100 jika saya bisa melakukannya
Kolonel Beauvel
1
Ini sangat membingungkan dari perspektif pendatang baru ctypes .. Tidak yakin apa yang terjadi, bahkan dengan penjelasannya.
DuckPuncher
69

Halaman ini memiliki contoh fungsi panggilan yang sangat sederhana dari file DLL.

Mengutip detail di sini untuk kelengkapan:

Sangat mudah untuk memanggil fungsi DLL dengan Python. Saya memiliki file DLL buatan sendiri dengan dua fungsi: adddan subyang mengambil dua argumen.

add(a, b)mengembalikan penambahan dua angka
sub(a, b)mengembalikan substraksi dua angka

Nama file DLL akan menjadi "demo.dll"

Program:

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

Keluaran:

Addition value:11
Substraction:9

atul
sumber
2
Tautan dalam jawaban ini rusak.
Kaliber64
10
Jika tautan tidak berfungsi untuk Anda jangan khawatir, itu adalah salin langsung. Anda tidak melewatkan informasi apa pun.
marsh
6

Mungkin dengan Dispatch:

from win32com.client import Dispatch

zk = Dispatch("zkemkeeper.ZKEM") 

Di mana zkemkeeper adalah file DLL terdaftar di sistem ... Setelah itu, Anda dapat mengakses fungsi hanya dengan memanggil mereka:

zk.Connect_Net(IP_address, port)
Carlos Gomez
sumber
Saya sedang mengerjakan zkemkeeper.ZKEM ini, apakah Anda tahu bagaimana saya bisa mendapatkan acara realtime dengan python?
Sam Ziggler
4

Membangun DLL dan menautkannya di bawah Python menggunakan ctypes

Saya menyajikan contoh yang sepenuhnya berhasil tentang bagaimana membangun shared librarydan menggunakannya di bawah Pythondengan cara ctypes. Saya mempertimbangkan Windowskasus ini dan menanganinya DLLs. Dibutuhkan dua langkah:

  1. Membangun DLL menggunakan kompiler Visual Studio baik dari baris perintah atau dari IDE;
  2. Tautkan DLL di bawah Python menggunakan ctypes.

Pustaka bersama

Yang shared librarysaya anggap sebagai berikut dan terdapat dalam testDLL.cppfile tersebut. Satu-satunya fungsi testDLLhanya menerima intdan mencetaknya.

#include <stdio.h>

extern "C" {

__declspec(dllexport)

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

} // extern "C"

Membangun DLL dari baris perintah

Untuk membangun DLLdengan Visual Studiodari jalankan baris perintah

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

untuk mengatur jalur sertakan dan kemudian jalankan

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

untuk membangun DLL.

Membangun DLLdari IDE

Atau, DLLdapat dibangun menggunakan Visual Studiosebagai berikut:

  1. File -> Baru -> Proyek;
  2. Diinstal -> Templat -> Visual C ++ -> Windows -> Win32 -> Win32Project;
  3. Lanjut;
  4. Jenis aplikasi -> DLL;
  5. Opsi tambahan -> Proyek kosong (pilih);
  6. Opsi tambahan -> Header yang dikompilasi (tidak dipilih);
  7. Project -> Properties -> Configuration Manager -> Platform solusi aktif: x64;
  8. Project -> Properties -> Configuration Manager -> Konfigurasi solusi aktif: Rilis.

Menghubungkan DLL di bawah Python

Di bawah Python, lakukan hal berikut

import os
import sys
from ctypes import *

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

lib.testDLL(3)
JackOLantern
sumber
Bagaimana jika DLL dalam paket python? Bagaimana saya mengaksesnya?
decadenza
3

ctypes akan menjadi hal yang termudah untuk digunakan tetapi (salah) menggunakannya membuat Python mengalami crash. Jika Anda mencoba melakukan sesuatu dengan cepat, dan Anda berhati-hati, itu bagus.

Saya akan mendorong Anda untuk memeriksa Boost Python . Ya, itu mengharuskan Anda menulis beberapa kode C ++ dan memiliki kompiler C ++, tetapi Anda sebenarnya tidak perlu belajar C ++ untuk menggunakannya, dan Anda bisa mendapatkan kompiler C ++ gratis (seperti dalam bir) dari Microsoft .

David Nehme
sumber
0

Jika DLL adalah tipe perpustakaan COM, maka Anda dapat menggunakan pythonnet.

pip install pythonnet

Kemudian dalam kode python Anda, coba yang berikut ini

import clr
clr.AddReference('path_to_your_dll')

kemudian instantiate objek sesuai kelas di DLL, dan akses metode di dalamnya.

sattva_venu
sumber