Вот я добрался и до Python. Так сказать – первые пробы пера. Но куда я в Python без Delphi? Сегодня столкнулся с тем, что в Python нужно было вызвать функцию из DLL, которая была написана много лет тому назад на Delphi.
Немного общей теории. Для вызова функций из сторонних библиотек в Python есть специальный модуль — ctypes. Этот модуль предоставляет разработчику C-совместимые типы данных и позволяет вызывать функции под различными операционными системами. Для загрузки динамических библиотек модуль ctypes предоставляет три метода:
Итак, у нас есть DLL работающая со строками:
library xyz; function TestW(const pText1, pText2: PChar): PChar; stdcall; begin Result := ...; end; function TestA(const pText1, pText2: PAnsiChar): PAnsiChar; stdcall; begin Result := ...; end; exports TestA, TestW; begin end.
Как вы видите, DLL экспортируют функции используя соглашение о вызовах stdcall, поэтому загружаем ее с помощью метода windll:
import ctypes text1 = 'Привет' text2 = 'Delphi' # загружаем DLL lib = ctypes.WinDLL('xyz.dll') # получаем функцию funcTest = lib.TestW # задаем типы параметров функции funcTest.argtypes = ctypes.c_wchar_p, ctypes.c_wchar_p # задаем тип результата функции funcTest.restype = ctypes.c_wchar_p # вызываем функцию и выводим результат ее выполнения print(funcTest(text1, text2))
Вызов функции с параметрами типа PAnsiChar немного сложнее:
import ctypes text1 = 'Привет' text2 = 'Delphi' lib = ctypes.WinDLL('xyz.dll') funcTest = lib.TestA funcTest.restype = ctypes.c_char_p funcTest.argtypes = ctypes.c_char_p, ctypes.c_char_p print(funcTest(text1.encode(), text2.encode()).decode())
Как вы видите, кроме изменения типа параметров, в коде появились вызовы методов encode() и decode(). Метод encode() кодирует параметры в байтовые строки. Если это не сделать, то во время выполнения программы мы получим ошибку:
ctypes.ArgumentError: argument 1: : wrong type
Метод decode() выполняет обратную операцию – он декодирует результат выполнения функции из байтовой строки. Если это не сделать, то print, при выводе результата функции, вместо русских букв выведет байты. Например, строка «Привет Python» превратится в «b’\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82 Python'».
Я рассмотрел приведенный здесь пример ctypes — Beginner и выполнил те же шаги с другим фрагментом кода C. Я создал .dll и .lib, используя приведенный здесь код C: http://wolfprojects.altervista.org/articles/dll-in-c-for-python/
//test.c __declspec(dllexport) int sum(int a, int b) { вернуть а + б; }
В моем файле wrapper.py есть это:
import ctypes testlib = ctypes.CDLL("C:\\Users\\xyz\\Documents\\Python\\test.dll")
Когда я запускаю скрипт, я получаю эту ошибку:
self._handle = _dlopen(self._name, режим)
OSError: [WinError 193] %1 не является допустимым приложением Win32
Если я использую
testlib = ctypes.LibraryLoader("C:\\Users\\xyz\\Documents\\Python\\test.dll")
, тогда я не получаю никаких ошибок при запуске скрипта. Но если я попытаюсь сделать это:
testlib.sum(3,4)
Я получаю сообщение об ошибке:
dll = self._dlltype(имя)
TypeError: объект ‘str’ не может быть вызван
DLL и . py находятся в одной папке. Может ли кто-нибудь помочь мне понять, что здесь происходит. Я потратил часы, пытаясь понять это, но наткнулся на стену. Спасибо.
1
Убедитесь, что ваш компилятор и версия Python являются 32-разрядными или 64-разрядными. Вы не можете смешивать, что является причиной OSError: [WinError 193] %1 не является допустимым приложением Win32
.
Затем убедитесь, что программа компилируется как программа на C, а не на C++. Это причина упоминания искажения имени в вашем ответе.
Пример (примечание компилятор для x86 не x64 :
C:\>cl /LD /W4 test.c Оптимизирующий компилятор Microsoft (R) C/C++ версии 17.00.61030 для x86 Авторское право (C) Microsoft Corporation. Все права защищены. тест.с Инкрементальный компоновщик Microsoft (R) версии 11.00.61030.0 Авторское право (C) Microsoft Corporation.Все права защищены. /out:test.dll /dll /implib:test.lib тест.obj Создание библиотеки test.lib и объекта test.exp
Теперь используйте 32-битный Python:
C:\>py -2 Python 2.7.13 (v2.7.13:a06454b1afa1, 17 декабря 2016 г., 20:42:59) [MSC v.1500 32 бит (Intel)] на win32 Введите «помощь», «авторское право», «кредиты» или «лицензия» для получения дополнительной информации. >>> из импорта ctypes * >>> lib = CDLL('тест') >>> lib.sum(2, 3) 5
Если вы компилируете как C++, вы все равно можете вызывать функции, экспортируя их как C, что предотвращает искажение имени C++:
test.cpp
внешний "C" __declspec(dllexport) int sum(int a, int b) { вернуть а + б; }
3
После дальнейших поисков я нашел решение. Компилятор C исказил имя функции, поэтому я получил ошибку атрибута при вызове метода суммы. Мне пришлось использовать link.exe, чтобы выяснить искаженное имя, а затем использовать метод getattr .
Подробнее и объяснение в этом посте: Python: доступ к функции DLL с использованием ctypes — доступ по функции *имя* не работает
1
Зарегистрироваться через Facebook
Зарегистрируйтесь, используя электронную почту и пароль
Электронная почта
Требуется, но никогда не отображается
Электронная почта
Требуется, но не отображается
Загрузите python.dll ниже, чтобы решить вашу проблему с dll. В настоящее время у нас есть 1 версия для этого файла.
Ошибки, связанные с python.dll, могут возникать по нескольким причинам. Например, ошибочное приложение: python.dll было удалено или потеряно, повреждено вредоносным программным обеспечением, присутствующим на вашем компьютере, или поврежден реестр Windows.
Наиболее часто встречающиеся сообщения об ошибках:
В подавляющем большинстве случаев решение состоит в правильной переустановке python.dll на вашем компьютере в системную папку Windows. В качестве альтернативы, некоторые программы, особенно игры для ПК, требуют, чтобы файл DLL был помещен в папку установки игры/приложения.
Подробные инструкции по установке см.
Версия
Архитектура
Размер файла
Язык
Компания
Описание
0.0.0.0
32
0,11 МБ
—
Неизвестно
—.MD5: 796a70daaece44ac5b901f4664a93cdb
SHA-1: 0849549bdf2624db5d1c454c295a0bd92db4d12f
Скачать
Размер ZIP-файла: 48,3 КБ
У вас есть информация, которой нет у нас?
Помог ли наш совет или мы что-то упустили?
На нашем форуме вы можете получить помощь как от квалифицированных технических специалистов, так и от сообщества в целом.