Як я можу використовувати файл DLL від Python?


186

Який найпростіший спосіб використовувати DLLфайл зсередини Python?

Зокрема, як це можна зробити, не записуючи додаткового C++коду обгортки, щоб піддавати його функціональності Python?

Нативну Pythonфункціональність настійно перевагу, ніж використання сторонньої бібліотеки.


@Remuze ти позначив неправильне запитання чи позначив неправильну відповідь? Вони обоє python, але я не бачу причин, чому ви знайшли б їх зовсім схожими (і я перевірив історію редагування, щоб переконатися, що вона не була якось ближче в якийсь момент минулого)
Foon

@foon hmmm так вибачте, я мав намір позначити ще одне питання як дублікат і поставити це :) Я здогадуюсь, що це показує, наскільки вони схожі!
Трев Девіс

Відповіді:


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Матеріал має всі типи С-типу даних ( int, char, short, void*, і т.д.) і може передавати за значенням або посиланням. Він також може повертати конкретні типи даних, хоча мій приклад цього не робить (API HLL повертає значення, змінюючи змінну, передану посиланням).


З точки зору конкретного прикладу, показаного вище, EHLLAPI IBM є досить послідовним інтерфейсом.

Усі виклики передають чотири недійсні покажчики (EHLLAPI посилає повертаючий код назад через четвертий параметр, вказівник на intтак, в той час як я вказуюint як тип повернення, я можу сміливо ігнорувати його) згідно документації IBM тут . Іншими словами, варіантом функції C буде:

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

Це створює єдину просту ctypesфункцію, здатну виконувати все, що надається бібліотеці EHLLAPI, але ймовірно, що для інших бібліотек знадобиться окрема ctypesфункція, налаштована на кожну функцію бібліотеки.

Повернене значення від WINFUNCTYPE - це прототип функції, але вам все одно доведеться встановити більше інформації про параметри (вище і вище типів). Кожен кортеж hllApiParamsмає параметр "напрям" (1 = вхід, 2 = вихід тощо), ім'я параметра та значення за замовчуванням - ctypesдетальну інформацію див. У документі

Коли ви отримаєте інформацію про прототип і параметри, ви можете створити Python "calllable", за hllApiдопомогою якого можна викликати функцію. Ви просто створити необхідну змінну ( p1через p4в моєму випадку) і викличте функцію з ними.


1
Здрастуйте, може пройти давно, коли хтось тут відповів, але я хотів щось знати, щоб зробити цю роботу саме для моєї програми. Не могли б ви сказати мені, що в цьому "HLLAPI"? Крім того, якщо я хочу отримати доступ до свого dll з функцією "void BoxProperties (подвійний L, подвійний H, подвійний W, подвійний & A, подвійний & V);" чи можете ви запропонувати мені, які зміни я повинен внести у вищевказаний код, щоб він працював? Ура.
Неофіл

4
Що саме робить hllApiParams? У чому сенс цих кортежів? Важко зіставити деякі речі цього прикладу з документацією.
Джонатан Райнхарт

1
@JonathonReinhart, я конкретизував конкретний приклад трохи з текстом внизу. Сподіваємось, це пояснює це трохи краще. Якщо ні, то повідомте мене, і я спробую ще раз :-)
paxdiablo

1
чудова відповідь, дуже допомагає через 6 років :) Я поставив би +100, якби міг це зробити!
Полковник Бовель

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, чи знаєте ви, як я можу отримати події в реальному часі в python?
Сем Зігглер

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 в пакеті python? Як отримати доступ до нього?
декаденса

3

ctypes буде найпростішим у використанні, але (неправильно) його використання робить Python предметом збоїв. Якщо ви намагаєтесь зробити щось швидко, і ви обережні, це чудово.

Я б радив вам перевірити Boost Python . Так, для цього потрібно написати якийсь код C ++ і мати компілятор C ++, але насправді не потрібно вчитися C ++, щоб ним користуватися, і ви можете отримати безкоштовний (як у пиві) компілятор C ++ від Microsoft .


0

Якщо DLL має тип бібліотеки COM, ви можете використовувати pythonnet.

pip install pythonnet

Потім у своєму коді python спробуйте наступне

import clr
clr.AddReference('path_to_your_dll')

потім інстанціюйте об'єкт відповідно до класу в DLL та отримайте доступ до методів всередині нього.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.