Как я могу использовать файл DLL из Python?

Какой самый простой способ использовать файл DLL из Python?

В частности, как это можно сделать без написания какого-либо дополнительного кода обёртки C++ для предоставления функциональности Python?

Встроенная функциональность Python настоятельно предпочтительнее, чем использование сторонней библиотеки.

5 ответов

Решение

Для простоты использования, 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 как тип возврата, я могу смело его игнорировать) согласно документации IBM здесь. Другими словами, вариант C функции будет:

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

Это делает для одного, простого ctypes Функция может делать все, что предоставляет библиотека EHLLAPI, но, вероятно, другим библиотекам потребуется отдельное ctypes функция устанавливается для библиотечной функции.

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

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

На этой странице приведен очень простой пример вызова функций из DLL-файла.

Перефразируя детали здесь для полноты:

В Python очень легко вызвать функцию DLL. У меня есть самодельный файл 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

Сборка 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)

ctypes можно использовать для доступа к dll, вот учебник:

http://docs.python.org/library/ctypes.html

Может быть с Dispatch:

from win32com.client import Dispatch

zk = Dispatch("zkemkeeper.ZKEM") 

Где zkemkeeper - это зарегистрированный файл DLL в системе... После этого вы можете получить доступ к функциям, просто вызвав их:

zk.Connect_Net(IP_address, port)

ctypes будет проще всего использовать, но (неправильное) его использование делает Python подверженным сбоям. Если вы пытаетесь что-то сделать быстро и осторожны, это здорово.

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

Если DLL имеет тип библиотеки COM, вы можете использовать pythonnet.

pip install pythonnet

Затем в вашем коде Python попробуйте следующее

import clr
clr.AddReference('path_to_your_dll')

затем создайте экземпляр объекта в соответствии с классом в DLL и получите доступ к его методам.

Другие вопросы по тегам