ฉันจะใช้ไฟล์ DLL จาก Python ได้อย่างไร?


186

วิธีที่ง่ายที่สุดในการใช้DLLไฟล์จากภายในPythonคืออะไร?

โดยเฉพาะวิธีนี้สามารถทำได้โดยไม่ต้องเขียนC++โค้ดwrapper เพิ่มเติมเพื่อแสดงฟังก์ชั่นPython?

พื้นเมืองPythonฟังก์ชันการทำงานที่เป็นที่ต้องการอย่างมากมากกว่าการใช้ห้องสมุดของบุคคลที่สาม


@Remuze คุณติดแท็กคำถามผิดหรือติดแท็กด้วยคำตอบที่ผิดหรือเปล่า? พวกเขาทั้งสองเป็นงูหลาม แต่ฉันไม่เห็นเหตุผลว่าทำไมคุณถึงพบพวกมันเหมือนกันหมด (และฉันตรวจสอบประวัติการแก้ไขเพื่อให้แน่ใจว่ามันไม่ได้ใกล้ที่ผ่านมาในบางจุด)
Foon

@ foon hmmm ใช่ขอโทษฉันหมายถึงการตั้งค่าคำถามอื่นที่ซ้ำกันและใส่คำถามนี้ :) ฉันเดาว่าแสดงให้เห็นว่าพวกเขาจะคล้ายกัน!
Trev Davies

คำตอบ:


154

เพื่อความสะดวกในการใช้งานctypesเป็นวิธีที่จะไป

ตัวอย่างของ ctypes ต่อไปนี้มาจากรหัสจริงที่ฉันเขียน (ใน Python 2.5) นี่เป็นวิธีที่ง่ายที่สุดที่ฉันค้นพบในการทำสิ่งที่คุณขอ

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

ctypesสิ่งมีทุกประเภทประเภท C ข้อมูล ( int, char, short, void*, และอื่น ๆ ) และสามารถส่งผ่านโดยค่าหรือการอ้างอิง นอกจากนี้ยังสามารถคืนค่าชนิดข้อมูลเฉพาะได้แม้ว่าตัวอย่างของฉันจะไม่ทำเช่นนั้น (HLL API คืนค่าโดยการแก้ไขตัวแปรที่ส่งผ่านโดยการอ้างอิง)


ในแง่ของตัวอย่างเฉพาะที่แสดงด้านบน EHLLAPI ของ IBM เป็นอินเตอร์เฟสที่สอดคล้องกัน

ทุกสายผ่านสี่โมฆะชี้ (EHLLAPI ส่งกลับส่งกลับรหัสผ่านพารามิเตอร์ที่สี่ตัวชี้ไปยังintดังนั้นในขณะที่ผมระบุintเป็นประเภทผลตอบแทนที่ฉันสามารถละเว้นได้) ตามเอกสารของไอบีเอ็มที่นี่ กล่าวอีกนัยหนึ่งตัวแปร C ของฟังก์ชันจะเป็น:

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

สิ่งนี้ทำให้ctypesฟังก์ชั่นที่เรียบง่ายและเรียบง่ายสามารถทำสิ่งใดก็ได้ที่ EHLLAPI ไลบรารีมอบให้ แต่ก็เป็นไปได้ว่าห้องสมุดอื่น ๆ จะต้องมีctypesการตั้งค่าฟังก์ชั่นแยกต่างหากต่อฟังก์ชั่นของห้องสมุด

ค่าส่งคืนจากWINFUNCTYPEเป็นฟังก์ชันต้นแบบ แต่คุณยังต้องตั้งค่าข้อมูลพารามิเตอร์เพิ่มเติม (สูงกว่าประเภท) tuple แต่ละอันhllApiParamsมีพารามิเตอร์ "direction" (1 = input, 2 = output และอื่น ๆ ) ชื่อพารามิเตอร์และค่าเริ่มต้น - ดูctypesdoco เพื่อดูรายละเอียด

เมื่อคุณมีข้อมูลต้นแบบและพารามิเตอร์คุณสามารถสร้าง Python "callable" hllApiเพื่อใช้เรียกฟังก์ชัน คุณเพียงแค่สร้างตัวแปรที่ต้องการ ( p1ผ่านp4ในกรณีของฉัน) และเรียกใช้ฟังก์ชันกับพวกเขา


1
สวัสดีอาจเป็นเวลานานแล้วที่มีคนตอบกลับมาที่นี่ แต่ฉันอยากรู้ว่าจะทำให้โปรแกรมนี้ทำงานได้อย่างสมบูรณ์ คุณช่วยบอกฉันหน่อยได้ไหมว่า "HLLAPI" ในเรื่องนี้คืออะไร? นอกจากนี้ถ้าฉันต้องการเข้าถึง dll ของฉันด้วยฟังก์ชั่น "void BoxProperties (double L, double H, double W, double & A, double & V);" คุณช่วยแนะนำฉันฉันควรจะทำการเปลี่ยนแปลงอะไรกับโค้ดด้านบนเพื่อให้มันใช้งานได้? ไชโย
Neophile

4
ไม่ว่าสิ่งที่hllApiParamsทำอย่างไร อะไรคือสิ่งอันดับ tuples? มันยากที่จะจับคู่บางสิ่งในตัวอย่างนี้กับเอกสาร
Jonathon Reinhart

1
@ JonathonReinhart ฉันได้รวบรวมตัวอย่างเฉพาะเล็กน้อยด้วยข้อความบางส่วนที่ด้านล่าง หวังว่านั่นจะอธิบายได้ดีขึ้นเล็กน้อย ถ้าไม่บอกให้ฉันรู้แล้วฉันจะลองอีกครั้ง :-)
paxdiablo

1
คำตอบที่ยอดเยี่ยมช่วยมาก 6 ปีหลังจาก :) ฉันจะใส่ +100 ถ้าฉันสามารถทำได้!
พันเอก Beauvel

1
นี่คือความสับสนอย่างมากจากมุมมองของผู้มาใหม่ ctypes .. ไม่แน่ใจว่าสิ่งที่เกิดขึ้นแม้จะมีคำอธิบาย
DuckPuncher

69

หน้านี้มีตัวอย่างง่ายๆของการเรียกฟังก์ชั่นจากไฟล์ DLL

การถอดความรายละเอียดที่นี่เพื่อความสมบูรณ์:

มันง่ายมากที่จะเรียกใช้ฟังก์ชัน DLL ใน Python ฉันมีไฟล์ DLL ที่สร้างตัวเองพร้อมกับฟังก์ชั่นสองอย่างaddและsubข้อโต้แย้งสองข้อ

add(a, b)ส่งคืนการเพิ่มตัวเลขสองตัว
sub(a, b)คืนการแทนที่ตัวเลขสองจำนวน

ชื่อของไฟล์ DLL จะเป็น "demo.dll"

โปรแกรม:

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

เอาท์พุท:

Addition value:11
Substraction:9


2
ลิงก์ในคำตอบนี้ใช้งานไม่ได้
Kaliber64

10
หากลิงค์ไม่ได้ผลสำหรับคุณไม่ต้องกังวลมันเป็นเพียงการคัดลอกโดยตรง คุณจะไม่พลาดข้อมูลใด ๆ
มาร์ช


6

อาจจะด้วยDispatch:

from win32com.client import Dispatch

zk = Dispatch("zkemkeeper.ZKEM") 

โดยที่ zkemkeeper เป็นไฟล์ DLL ที่ลงทะเบียนไว้ในระบบ ... หลังจากนั้นคุณสามารถเข้าถึงฟังก์ชั่นต่างๆ

zk.Connect_Net(IP_address, port)

ฉันกำลังทำงานกับ zkemkeeper.ZKEM นี้คุณรู้ไหมว่าฉันจะได้รับเหตุการณ์แบบเรียลไทม์ในไพ ธ อนได้อย่างไร
Sam Ziggler

4

สร้าง DLL และเชื่อมโยงภายใต้ Python โดยใช้ ctypes

ผมนำเสนอเป็นตัวอย่างที่ทำงานอย่างเต็มที่เกี่ยวกับวิธีการสร้างshared libraryและใช้ภายใต้การโดยวิธีการของPython ctypesฉันพิจารณาคดีและข้อตกลงกับWindows DLLsต้องการสองขั้นตอน:

  1. สร้าง DLL โดยใช้คอมไพเลอร์ของ Visual Studio จากบรรทัดคำสั่งหรือจาก IDE
  2. เชื่อมโยง DLL ภายใต้ Python โดยใช้ ctypes

ห้องสมุดสาธารณะ

shared libraryผมพิจารณาคือต่อไปนี้และมีอยู่ในtestDLL.cppไฟล์ ฟังก์ชั่นเดียวที่testDLLเพิ่งได้รับintและพิมพ์

#include <stdio.h>

extern "C" {

__declspec(dllexport)

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

} // extern "C"

สร้าง DLL จากบรรทัดคำสั่ง

เพื่อสร้างDLLด้วยVisual Studioจากบรรทัดคำสั่งทำงาน

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

เพื่อตั้งค่าเส้นทางรวมแล้วเรียกใช้

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

เพื่อสร้าง DLL

การสร้างDLLจาก IDE

หรือมิฉะนั้นDLLสามารถสร้างได้โดยใช้Visual Studioดังนี้:

  1. ไฟล์ -> ใหม่ -> โครงการ;
  2. ติดตั้ง -> แม่แบบ -> Visual C ++ -> Windows -> Win32 -> Win32Project;
  3. ต่อไป;
  4. แอปพลิเคชัน -> DLL;
  5. ตัวเลือกเพิ่มเติม -> โครงการที่ว่างเปล่า (เลือก);
  6. ตัวเลือกเพิ่มเติม -> ส่วนหัวที่คอมไพล์แล้ว (ยกเลิกการเลือก);
  7. โครงการ -> คุณสมบัติ -> เครื่องมือจัดการการกำหนดค่า -> แพลตฟอร์มโซลูชันที่ใช้งาน: x64;
  8. โครงการ -> คุณสมบัติ -> เครื่องมือจัดการการกำหนดค่า -> การกำหนดค่าโซลูชันที่ใช้งาน: ปล่อย

การเชื่อมโยง DLL ภายใต้ Python

ภายใต้ Python ให้ทำดังต่อไปนี้

import os
import sys
from ctypes import *

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

lib.testDLL(3)

เกิดอะไรขึ้นถ้า DLL ในแพคเกจหลาม? ฉันจะเข้าถึงมันได้อย่างไร
Decadenza

3

ctypes จะเป็นสิ่งที่ง่ายที่สุดในการใช้งาน แต่การใช้ผิดพลาดทำให้ Python ถูกกระแทก หากคุณกำลังพยายามทำบางสิ่งอย่างรวดเร็วและคุณก็ระวังตัวมันยอดเยี่ยม

ฉันอยากจะแนะนำให้คุณตรวจสอบBoost หลาม ใช่มันต้องการให้คุณเขียน c ++ โค้ดบางส่วนและมีการแปลภาษา C ++ แต่คุณไม่จำเป็นต้องจริงที่จะเรียนรู้ภาษา C ++ ที่จะใช้มันและคุณจะได้รับฟรี (ในเบียร์) C ++ คอมไพเลอร์จากไมโครซอฟท์


0

ถ้า DLL เป็นชนิดไลบรารี COM คุณสามารถใช้ pythonnet

pip install pythonnet

จากนั้นในรหัสไพ ธ อนของคุณลองต่อไปนี้

import clr
clr.AddReference('path_to_your_dll')

จากนั้นยกตัวอย่างวัตถุตามระดับใน DLL และเข้าถึงวิธีการภายใน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.