Làm cách nào để sử dụng tệp DLL từ Python?


186

Cách dễ nhất để sử dụng một DLLtập tin từ bên trong là Pythongì?

Cụ thể, làm thế nào điều này có thể được thực hiện mà không cần viết bất kỳ C++mã trình bao bọc bổ sung nào để hiển thị chức năng Python?

PythonChức năng gốc được ưu tiên mạnh mẽ hơn so với sử dụng thư viện của bên thứ ba.


@Remuze bạn đã gắn thẻ câu hỏi sai hoặc gắn thẻ với câu trả lời sai? Cả hai đều là trăn, nhưng tôi không hiểu lý do tại sao bạn lại thấy chúng giống nhau (và tôi đã kiểm tra lịch sử sửa đổi để chắc chắn rằng nó không gần gũi hơn vào một lúc nào đó trong quá khứ)
Foon

@foon hmmm vâng, xin lỗi, tôi muốn đánh dấu một câu hỏi khác là trùng lặp và đặt câu hỏi này :) Tôi đoán điều đó cho thấy chúng giống nhau như thế nào!
Trev Davies

Câu trả lời:


153

Để dễ sử dụng, ctypes là cách để đi.

Ví dụ sau đây về ctypes là từ mã thực tế tôi đã viết (bằng Python 2.5). Đây là cách dễ nhất mà tôi đã tìm thấy để làm những gì bạn yêu cầu.

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

Các ctypesthứ có tất cả các loại C-kiểu dữ liệu ( int, char, short, void*, và vân vân) và có thể vượt qua bởi giá trị hoặc tham khảo. Nó cũng có thể trả về các loại dữ liệu cụ thể mặc dù ví dụ của tôi không làm điều đó (API HLL trả về các giá trị bằng cách sửa đổi một biến được truyền bằng tham chiếu).


Xét về ví dụ cụ thể được trình bày ở trên, EHLLAPI của IBM là một giao diện khá nhất quán.

Tất cả các cuộc gọi đều vượt qua bốn con trỏ void (EHLLAPI gửi mã trả về qua tham số thứ tư, một con trỏ tới int, trong khi tôi chỉ định intlà kiểu trả về, tôi có thể bỏ qua nó một cách an toàn) theo tài liệu của IBM ở đây . Nói cách khác, biến thể C của hàm sẽ là:

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

Điều này làm cho một ctypeschức năng đơn giản có thể làm bất cứ điều gì mà thư viện EHLLAPI cung cấp, nhưng có khả năng các thư viện khác sẽ cần một ctypeschức năng riêng được thiết lập cho mỗi chức năng thư viện.

Giá trị trả về từ WINFUNCTYPElà một nguyên mẫu hàm nhưng bạn vẫn phải thiết lập thêm thông tin tham số (hơn và hơn các loại). Mỗi bộ trong hllApiParamscó một tham số "hướng" (1 = đầu vào, 2 = đầu ra, v.v.), tên tham số và giá trị mặc định - xem tài liệu ctypesđể biết chi tiết

Khi bạn có thông tin về nguyên mẫu và tham số, bạn có thể tạo Python "có thể gọi được" hllApiđể gọi hàm. Bạn chỉ cần tạo biến cần thiết ( p1thông qua p4trường hợp của tôi) và gọi hàm với chúng.


1
Xin chào, có thể đã lâu rồi kể từ khi ai đó trả lời ở đây nhưng tôi muốn biết điều gì đó để làm cho công việc này chính xác cho chương trình của tôi. Bạn có thể cho tôi biết "HLLAPI" trong cái này là gì không? Ngoài ra, nếu tôi muốn truy cập dll của mình với chức năng "void BoxProperIES (double L, double H, double W, double & A, double & V);" bạn có thể gợi ý cho tôi những thay đổi nào tôi nên thực hiện đối với đoạn mã trên để làm cho nó hoạt động không? Chúc mừng.
Neophile

4
Chính xác thì hllApiParamslàm gì? Điểm của những bộ dữ liệu đó là gì? Thật khó để kết hợp một số điều trong ví dụ này với tài liệu.
Jonathon Reinhart

1
@JonathonReinhart, tôi đã đưa ra ví dụ cụ thể một chút với một số văn bản ở phía dưới. Hy vọng rằng, điều đó giải thích nó tốt hơn một chút. Nếu không, hãy cho tôi biết và tôi sẽ thử lại :-)
paxdiablo

1
câu trả lời tuyệt vời, giúp rất nhiều 6 năm sau :) Tôi sẽ đặt +100 nếu tôi có thể làm được!
Đại tá Beauvel

1
Điều này là siêu khó hiểu từ một quan điểm người mới làm việc của ctypes .. Không chắc chắn chính xác những gì đang xảy ra, ngay cả với lời giải thích.
DuckPuncher

69

Trang này có một ví dụ rất đơn giản về chức năng gọi từ tệp DLL.

Diễn giải các chi tiết ở đây cho đầy đủ:

Thật dễ dàng để gọi một hàm DLL trong Python. Tôi có một tệp DLL tự tạo với hai hàm: addsubcó hai đối số.

add(a, b)trả về phép cộng hai số
sub(a, b)trả về giá trị con của hai số

Tên của tệp DLL sẽ là "demo.dll"

Chương trình:

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

Đầu ra:

Addition value:11
Substraction:9


2
Liên kết trong câu trả lời này bị hỏng.
Kaliber64

10
Nếu liên kết không hoạt động đối với bạn, đừng lo lắng, đó là bản sao chép trực tiếp. Bạn không thiếu bất kỳ thông tin.
đầm lầy


6

Có thể với Dispatch:

from win32com.client import Dispatch

zk = Dispatch("zkemkeeper.ZKEM") 

Trong đó zkemkeeper là một tệp DLL đã đăng ký trên hệ thống ... Sau đó, bạn có thể truy cập các chức năng chỉ bằng cách gọi chúng:

zk.Connect_Net(IP_address, port)

Tôi đang làm việc trên zkemkeeper.ZKEM này, bạn có biết làm thế nào tôi có thể nhận được các sự kiện thời gian thực trong python không?
Sam Ziggler

4

Xây dựng một DLL và liên kết nó dưới Python bằng ctypes

Tôi trình bày một ví dụ hoạt động đầy đủ về cách xây dựng shared libraryvà sử dụng nó theo Pythonphương tiện ctypes. Tôi xem xét Windowstrường hợp và giải quyết DLLs. Cần hai bước:

  1. Xây dựng DLL bằng trình biên dịch của Visual Studio hoặc từ dòng lệnh hoặc từ IDE;
  2. Liên kết DLL dưới Python bằng ctypes.

Thư viện dùng chung

Các shared librarytôi xem xét là những điều sau đây và được chứa trong các testDLL.cpptập tin. Hàm duy nhất testDLLchỉ nhận được một intvà in nó.

#include <stdio.h>

extern "C" {

__declspec(dllexport)

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

} // extern "C"

Xây dựng DLL từ dòng lệnh

Để xây dựng một DLLvới Visual Studiotừ dòng lệnh chạy

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

để đặt đường dẫn bao gồm và sau đó chạy

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

để xây dựng DLL.

Xây dựng DLLtừ IDE

Ngoài ra, DLLcó thể được xây dựng bằng cách sử dụng Visual Studionhư sau:

  1. Tệp -> Mới -> Dự án;
  2. Đã cài đặt -> Mẫu -> Visual C ++ -> Windows -> Win32 -> Win32Project;
  3. Kế tiếp;
  4. Loại ứng dụng -> DLL;
  5. Tùy chọn bổ sung -> Dự án trống (chọn);
  6. Tùy chọn bổ sung -> Tiêu đề được biên dịch sẵn (bỏ chọn);
  7. Dự án -> Thuộc tính -> Trình quản lý cấu hình -> Nền tảng giải pháp hoạt động: x64;
  8. Dự án -> Thuộc tính -> Trình quản lý cấu hình -> Cấu hình giải pháp hoạt động: Phát hành.

Liên kết DLL theo Python

Trong Python, làm như sau

import os
import sys
from ctypes import *

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

lib.testDLL(3)

Nếu DLL trong gói python thì sao? Làm thế nào để tôi truy cập nó?
decadenza

3

ctypes sẽ là thứ dễ sử dụng nhất nhưng (mis) sử dụng nó khiến cho chủ đề Python bị sập. Nếu bạn đang cố gắng làm điều gì đó nhanh chóng, và bạn cẩn thận, điều đó thật tuyệt.

Tôi sẽ khuyến khích bạn kiểm tra Boost Python . Đúng, nó yêu cầu bạn viết một số mã C ++ và có trình biên dịch C ++, nhưng bạn thực sự không cần phải học C ++ để sử dụng nó và bạn có thể nhận được trình biên dịch C ++ miễn phí (như bia) từ Microsoft .


0

Nếu DLL thuộc loại thư viện COM, thì bạn có thể sử dụng pythonnet.

pip install pythonnet

Sau đó, trong mã python của bạn, hãy thử như sau

import clr
clr.AddReference('path_to_your_dll')

sau đó khởi tạo một đối tượng theo lớp trong DLL và truy cập các phương thức bên trong nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.