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


186

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

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

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


@Remuze вы пометили неправильный вопрос или пометить неправильный ответ? Они оба питоны, но я не вижу причин, почему вы могли бы найти их похожими (и я проверил историю изменений, чтобы убедиться, что она не была как-то ближе в какой-то момент в прошлом)
Foon

@foon хммм да извините, я хотел пометить другой вопрос как дубликат и поставить этот :) Я думаю, это показывает, насколько они похожи!
Трев Дэвис

Ответы:


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*, и т.д.) и может передавать по значению или ссылке. Он также может возвращать определенные типы данных, хотя мой пример этого не делает (HLL API возвращает значения путем изменения переменной, переданной по ссылке).


С точки зрения конкретного примера, показанного выше, EHLLAPI от IBM представляет собой довольно непротиворечивый интерфейс.

Все вызовы проходят четыре пустых указателя (EHLLAPI отправляет код возврата через четвертый параметр, указатель на intso, хотя я указываю intв качестве типа возврата, я могу смело его игнорировать) согласно документации IBM здесь . Другими словами, вариант C функции будет:

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

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

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

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


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

4
Что именно делает hllApiParams? Какой смысл этих кортежей? Трудно сопоставить некоторые вещи в этом примере с документацией.
Джонатон Рейнхарт

1
@JonathonReinhart, я немного конкретизировал конкретный пример с текстом внизу. Надеюсь, это объясняет это немного лучше. Если нет, дайте мне знать, и я попробую еще раз :-)
paxdiablo

1
отличный ответ, очень помогает через 6 лет :) Я бы поставил +100, если бы мог это сделать!
полковник Бовель

1
Это очень запутанно с точки зрения новичков ctypes. Не совсем уверен, что происходит, даже с объяснениями.
DuckPuncher

69

На этой странице приведен очень простой пример вызова функций из 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


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.