Автор Тема: Запуск .dll из Python  (Прочитано 616 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Samovar

  • Житель
  • Пятигорье
Запуск .dll из Python
« : 27 Ноября 2016, 12:23:34 »

Хотя, конечно, правильней  вопрос будет звучать как "обращение к функциям .dll из Python".
Это возможно? Если да, то как?
¯\_(ツ)_/¯

Оффлайн Striver

  • Житель
    • http://striver00.ru
Re: Запуск .dll из Python
« Ответ #1 : 27 Ноября 2016, 13:34:54 »
Если это просто левая, никак не связанная с системой DLL, то, скорее всего, без написания расширения на C не обойтись.

Если же это зарегистрированный в винде COM-объект, то в Питоне есть модуль для работы с такими объектами.
Я делал это так:
from win32com.client import Dispatch
try:
    comobj=Dispatch("Super_puperDLL.ComObject")
except:
    print ("COM-объект не найден")
    sys.exit(1)
где вместо "Super_puperDLL.ComObject" ставишь правильное название COM-объекта. Все существующие COM-объекты в винде можно посмотреть, например, в Excel, точнее, в его VisualBasic-редакторе, скорее всего в какой-нибудь VisualStudio тоже можно.

Далее пользуешься методами объекта в переменной comobj. Имена и аргументы этих методов разные и зависят от DLL.

Оффлайн Samovar

  • Житель
  • Пятигорье
Re: Запуск .dll из Python
« Ответ #2 : 27 Ноября 2016, 15:59:58 »
Спасибо за ответ, но речь не про COM, а про обычные .dll ( .so, если не ошибаюсь, в Юниксах). Так как Python великий тормоз, проще написать функции на каком либо реальном ЯП и скомпилировать в .dll, но встаёт вопрос как из Python вызывать эти функции, и можно ли вообще?
« Последнее редактирование: 27 Ноября 2016, 16:17:52 от Samovar »
¯\_(ツ)_/¯

Оффлайн LanuHum

  • Житель
Re: Запуск .dll из Python
« Ответ #3 : 27 Ноября 2016, 18:02:25 »
Спасибо за ответ, но речь не про COM, а про обычные .dll ( .so, если не ошибаюсь, в Юниксах). Так как Python великий тормоз, проще написать функции на каком либо реальном ЯП и скомпилировать в .dll, но встаёт вопрос как из Python вызывать эти функции, и можно ли вообще?

Самое простое использование ctypes:
https://docs.python.org/3.5/library/ctypes.html#module-ctypes
>>> from ctypes import *
>>> print(windll.kernel32) 
<WinDLL 'kernel32', handle ... at ...>
>>> print(cdll.msvcrt)     
<CDLL 'msvcrt', handle ... at ...>
>>> libc = cdll.msvcrt     
Другой вариант здесь:
http://blender-3d.ru/forum/index.php/topic,1529.0.html
Третий вариант здесь:
https://docs.python.org/3/extending/extending.html
Четвёртый вариант:
https://ru.wikipedia.org/wiki/SWIG
Пятый вариант:
https://habrahabr.ru/post/168083/

Оффлайн LanuHum

  • Житель
Re: Запуск .dll из Python
« Ответ #4 : 27 Ноября 2016, 18:24:25 »
К моему предыдущему посту.
Вот здесь что-то про FreeBasic, Python, ctypes:
http://www.freebasic.net/forum/viewtopic.php?t=3946

Оффлайн Samovar

  • Житель
  • Пятигорье
Re: Запуск .dll из Python
« Ответ #5 : 28 Ноября 2016, 15:19:08 »
Спасибо за ответ, но речь не про COM, а про обычные .dll ( .so, если не ошибаюсь, в Юниксах). Так как Python великий тормоз, проще написать функции на каком либо реальном ЯП и скомпилировать в .dll, но встаёт вопрос как из Python вызывать эти функции, и можно ли вообще?

Самое простое использование ctypes:
https://docs.python.org/3.5/library/ctypes.html#module-ctypes
>>> from ctypes import *
>>> print(windll.kernel32) 
<WinDLL 'kernel32', handle ... at ...>
>>> print(cdll.msvcrt)     
<CDLL 'msvcrt', handle ... at ...>
>>> libc = cdll.msvcrt     
Другой вариант здесь:
http://blender-3d.ru/forum/index.php/topic,1529.0.html
Третий вариант здесь:
https://docs.python.org/3/extending/extending.html
Четвёртый вариант:
https://ru.wikipedia.org/wiki/SWIG
Пятый вариант:
https://habrahabr.ru/post/168083/

Спасибо Ланухумыч!
¯\_(ツ)_/¯

Оффлайн Samovar

  • Житель
  • Пятигорье
Re: Запуск .dll из Python
« Ответ #6 : 28 Ноября 2016, 15:20:22 »
К моему предыдущему посту.
Вот здесь что-то про FreeBasic, Python, ctypes:
http://www.freebasic.net/forum/viewtopic.php?t=3946

А за это спасибо вдвойне! Это то, что нужно! Буду пробовать.
¯\_(ツ)_/¯

Оффлайн LanuHum

  • Житель
Re: Запуск .dll из Python
« Ответ #7 : 11 Декабря 2016, 14:39:20 »
А за это спасибо вдвойне! Это то, что нужно! Буду пробовать.

Как выяснилось, ctypes ускоряет работу программы ни на столько насколько хотелось бы.
Это худший вариант.

 Лучший вариант, как мне показалось, писать на С++ используя boost-python. Но, как сейчас убедился, с третьим питоном проблема:
ImportError: /home/leonid/workspace/programming/python_c++/extend/simpleExample.cpython-34m.so: undefined symbol: _ZN5boost6python6detail11init_moduleER11PyModuleDefPFvvE
Больше всего пользуют, именно, boost и, меньше всего python3, ибо ответы на вопросы пользователей "какого ляда символ не объявлен?" выглядят неадекватно. Так что, если писать модули для использования в Блендере, используя boost, можно зря потратить нервы.

SWIG потребует кроме изучения С\С++ ещё и изучение написания интерфейсных файлов, про которые на русском написано только про Hello World! Да, именно на русском написано, как питоном вызвать сишную функцию выводящую в терминал(смд) "Hello, World!"
Очень нужная информация, герои те, кто нам её предоставил. Важнее нет ничего, кроме как таким способом в консоли писать два слова.

Cython, тоже, вижу, не популярен, но разобраться можно, если не потребуется включения сторонних библиотек. Я не смог создать текстовой файл. Пишет бинарник, и ноль информации на просторах инета про написание текстовых файлов ситоном. Зато с обычной арифметикой тут удобно и можно отрубать блокировку питоном многопоточности.

Всей этой хрени можно бы было избежать, если бы я хоть где-то нашёл пример написания кода питонового модуля на С, который можно собрать обычной командой g++. Даже, "Хелоу, мир!" не нашёл. То setuptools нужно, то distutils, то ещё фигню какую-то.

Оффлайн LanuHum

  • Житель
Re: Запуск .dll из Python
« Ответ #8 : 11 Декабря 2016, 21:51:19 »
Ага, разобрался с boost-python3. Невнимательно посмотрел. Есть пакет, но был не установлен.
Пример нашёл в интернете коротенький. Файл greet_binding.cpp:
#include <iostream>
#include <boost/python/def.hpp>
#include <boost/python/module.hpp>
using namespace std;
namespace bp = boost::python;
void say_greeting(const char* name)
{
cout << "Hello, " << name << "!\n";
}
BOOST_PYTHON_MODULE(greet)
{
bp::def("say_greeting", say_greeting);
}
Перейдя в каталог с файлом нужно собрать его командой (линукс):
g++ greet_binding.cpp -I/usr/include/python3.4m -lboost_python3 -lpython3.4m -o greet.so -shared -fPIC
Теперь в каталоге появился файл greet.so. Здесь же размещаем файл test.py с текстом:
import greet
a = greet.say_greeting("Eric")
print (a)
Запускаем файл из консоли, читаем в консоли:
Hello, Eric!
None

Хоть это и примитивный Hello World, но он показывает все задействованные механизмы создания библиотеки на плюсах как модуля для питона.
Разумеется, это подходит для случаев самописного модуля в виде .so или .dll. Если бинарник уже кем-то создан, то ctypes.
Кстати, с кириллицей проблем нет в линуксе при использовании boost.
« Последнее редактирование: 11 Декабря 2016, 22:52:54 от LanuHum »

Оффлайн Samovar

  • Житель
  • Пятигорье
Re: Запуск .dll из Python
« Ответ #9 : 14 Декабря 2016, 17:27:31 »
Ланухумыч, меня интересует прежде всего вариант ctypes. Попробовал на IDE Python 2.6.2 врубать скомпилированную на FB либу... работает (правда с кодировками видимо проблема...но это ничего)... Пробовал из Blender'a тоже самое...нихрена не работает... как в 2.49 так и в 2.78... ругается постоянно...
Вбил в интерактивной консоли Блендера >>>help ('_ctypes')
выдало дохрена инфы... и не пнонял почему эта команда (модуль... я особо не шарю) начинается с подчёркивания в Блендере?..
Если можешь, пришли рабочий пример скрипта, пожалуйста, а dll-ку я сам соберу.
¯\_(ツ)_/¯

Оффлайн Striver

  • Житель
    • http://striver00.ru
Re: Запуск .dll из Python
« Ответ #10 : 14 Декабря 2016, 18:36:58 »
Цитировать
и не пнонял почему эта команда (модуль... я особо не шарю) начинается с подчёркивания в Блендере?..
ctypes - пакет модулей, написанных на питоне (находится в blender-2.78-windows64\2.78\python\lib\ctypes\*)
_ctypes - связанный с этим пакетом бинарный файл blender-2.78-windows64\2.78\python\lib\_ctypes.pyd )
импортировать надо пакет ctypes, а бинарник он сам должен подтянуть.

Цитировать
нихрена не работает... как в 2.49 так и в 2.78... ругается постоянно...
чо конкретно пишет?

Оффлайн Samovar

  • Житель
  • Пятигорье
Re: Запуск .dll из Python
« Ответ #11 : 14 Декабря 2016, 18:44:30 »

dll на FB


' This function adds two numbers (i've taken it from Freebasic manuel !)
Function AddNumbers CDECL Alias "AddNumbers" ( ByVal operand1 As Integer, ByVal operand2 As Integer) As Integer Export
   AddNumbers = operand1 + operand2
End Function         


' This one shows uppercase text
Function ShowText CDECL Alias "ShowText" (ByVal MyText As String)  As Integer Export     
   Print ucase(Mytext)
   Return 1
End Function
Python
#__ LOAD MODULE CTYPE __
from ctypes import *


#__ LOAD THE DLL __
libFreeBasic = cdll.LoadLibrary("mydll.dll")


#__ CALL FUNCION WITH INTEGER PARAMETER __
print (libFreeBasic.AddNumbers(5,7))


#__ CALL FUNCTION WITH STRING PARAMETER AND GET RETURN CODE__
s_MyText = "Hello"
c_MyText = c_char_p(s_MyText)
RetCode = libFreeBasic.ShowText(s_MyText)


RetMsg = "Return code : " + str(RetCode)
print (RetMsg)
Цитировать



Traceback (most recent call last):
  File "C:\Users\Den\Desktop\FB\testdll.blend\Text", line 5, in <module>
  File "C:\Program Files\Blender Foundation\Blender\2.78\python\lib\ctypes\__ini
t__.py", line 425, in LoadLibrary
    return self._dlltype(name)
  File "C:\Program Files\Blender Foundation\Blender\2.78\python\lib\ctypes\__ini
t__.py", line 347, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] Не найден указанный модуль
Error: Python script fail, look in the console for now...
¯\_(ツ)_/¯

Оффлайн Striver

  • Житель
    • http://striver00.ru
Re: Запуск .dll из Python
« Ответ #12 : 14 Декабря 2016, 19:05:59 »
Цитировать
OSError: [WinError 126] Не найден указанный модуль
В Notepad++ перевёл в UTF8 эту хрень:
РќРµ найден указанный модуль = Не найден указанный модуль
Т.е. он не находит твою dll-ку.

Скинь её сюда (неохота у себя Basic ставить), попробую из Блендера подключиться.

Оффлайн Samovar

  • Житель
  • Пятигорье
Re: Запуск .dll из Python
« Ответ #13 : 14 Декабря 2016, 19:13:33 »
Вот малёха переделанная для x64... должна окно 400х400 нарисовать...


' This function adds two numbers (i've taken it from Freebasic manuel !)
Function AddNumbers CDECL Alias "AddNumbers" ( ByVal operand1 As Integer, ByVal operand2 As Integer) As Integer Export
   AddNumbers = operand1 + operand2
End Function         


' This one shows uppercase text
Function ShowText CDECL Alias "ShowText" (ByVal MyText As String)  As Integer Export     
   'Print ucase(Mytext)
   ScreenRes 400,400
   Return 1
End Function
¯\_(ツ)_/¯

Оффлайн Striver

  • Житель
    • http://striver00.ru
Re: Запуск .dll из Python
« Ответ #14 : 14 Декабря 2016, 19:29:21 »
вписал полный путь, модуль проимпортировался:
>>> #__ LOAD THE DLL __
>>> libFreeBasic = cdll.LoadLibrary("mydll.dll")
Traceback (most recent call last):
  File "<blender_console>", line 1, in <module>
  File "I:\Programs64\Blender\blender-2.78-windows64\2.78\python\lib\ctypes\__init__.py", line 425, in LoadLibrary
    return self._dlltype(name)
  File "I:\Programs64\Blender\blender-2.78-windows64\2.78\python\lib\ctypes\__init__.py", line 347, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: [WinError 126] Не найден указанный модуль

>>> libFreeBasic = cdll.LoadLibrary(r"D:\moe\blender\Vopros\mydll.dll")
>>> print (libFreeBasic.AddNumbers(5,7))
12

на функцию ShowText появилось окошко.

 

* По форуму

* Последние вложения

Sizes.jpg
Скачано: 10
Автор: Dmi3ryd
paticles.jpg
Скачано: 5
Автор: Dmi3ryd
Снимок 1.PNG
Скачано: 3
Автор: atmk
Снимок.PNG
Скачано: 3
Автор: atmk
Screw.jpg
Скачано: 8
Автор: Dmi3ryd