3d форум по Blender

Другое => Программирование (любое) => Тема начата: Samovar от 27 Ноябрь 2016, 12:23:34

Название: Запуск .dll из Python
Отправлено: Samovar от 27 Ноябрь 2016, 12:23:34

Хотя, конечно, правильней  вопрос будет звучать как "обращение к функциям .dll из Python".
Это возможно? Если да, то как?
Название: Re: Запуск .dll из Python
Отправлено: Striver от 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.
Название: Re: Запуск .dll из Python
Отправлено: Samovar от 27 Ноябрь 2016, 15:59:58
Спасибо за ответ, но речь не про COM, а про обычные .dll ( .so, если не ошибаюсь, в Юниксах). Так как Python великий тормоз, проще написать функции на каком либо реальном ЯП и скомпилировать в .dll, но встаёт вопрос как из Python вызывать эти функции, и можно ли вообще?
Название: Re: Запуск .dll из Python
Отправлено: LanuHum от 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/
Название: Re: Запуск .dll из Python
Отправлено: LanuHum от 27 Ноябрь 2016, 18:24:25
К моему предыдущему посту.
Вот здесь что-то про FreeBasic, Python, ctypes:
http://www.freebasic.net/forum/viewtopic.php?t=3946
Название: Re: Запуск .dll из Python
Отправлено: Samovar от 28 Ноябрь 2016, 15:19:08
Спасибо за ответ, но речь не про COM, а про обычные .dll ( .so, если не ошибаюсь, в Юниксах). Так как Python великий тормоз, проще написать функции на каком либо реальном ЯП и скомпилировать в .dll, но встаёт вопрос как из Python вызывать эти функции, и можно ли вообще?
Самое простое использование ctypes:
https://docs.python.org/3.5/library/ctypes.html#module-ctypes (http://blender-3d.ru/forum/go.php?url=aHR0cHM6Ly9kb2NzLnB5dGhvbi5vcmcvMy41L2xpYnJhcnkvY3R5cGVzLmh0bWwjbW9kdWxlLWN0eXBlcw==)
>>> 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 (http://blender-3d.ru/forum/go.php?url=aHR0cHM6Ly9kb2NzLnB5dGhvbi5vcmcvMy9leHRlbmRpbmcvZXh0ZW5kaW5nLmh0bWw=)
Четвёртый вариант:
https://ru.wikipedia.org/wiki/SWIG (http://blender-3d.ru/forum/go.php?url=aHR0cHM6Ly9ydS53aWtpcGVkaWEub3JnL3dpa2kvU1dJRw==)
Пятый вариант:
https://habrahabr.ru/post/168083/ (http://blender-3d.ru/forum/go.php?url=aHR0cHM6Ly9oYWJyYWhhYnIucnUvcG9zdC8xNjgwODMv)
Спасибо Ланухумыч!
Название: Re: Запуск .dll из Python
Отправлено: Samovar от 28 Ноябрь 2016, 15:20:22
К моему предыдущему посту.
Вот здесь что-то про FreeBasic, Python, ctypes:
http://www.freebasic.net/forum/viewtopic.php?t=3946 (http://blender-3d.ru/forum/go.php?url=aHR0cDovL3d3dy5mcmVlYmFzaWMubmV0L2ZvcnVtL3ZpZXd0b3BpYy5waHA/dD0zOTQ2)
А за это спасибо вдвойне! Это то, что нужно! Буду пробовать.
Название: Re: Запуск .dll из Python
Отправлено: LanuHum от 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, то ещё фигню какую-то.
Название: Re: Запуск .dll из Python
Отправлено: LanuHum от 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.
Название: Re: Запуск .dll из Python
Отправлено: Samovar от 14 Декабрь 2016, 17:27:31
Ланухумыч, меня интересует прежде всего вариант ctypes. Попробовал на IDE Python 2.6.2 врубать скомпилированную на FB либу... работает (правда с кодировками видимо проблема...но это ничего)... Пробовал из Blender'a тоже самое...нихрена не работает... как в 2.49 так и в 2.78... ругается постоянно...
Вбил в интерактивной консоли Блендера >>>help ('_ctypes')
выдало дохрена инфы... и не пнонял почему эта команда (модуль... я особо не шарю) начинается с подчёркивания в Блендере?..
Если можешь, пришли рабочий пример скрипта, пожалуйста, а dll-ку я сам соберу.
Название: Re: Запуск .dll из Python
Отправлено: Striver от 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... ругается постоянно...
чо конкретно пишет?
Название: Re: Запуск .dll из Python
Отправлено: Samovar от 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...
Название: Re: Запуск .dll из Python
Отправлено: Striver от 14 Декабрь 2016, 19:05:59
Цитировать
OSError: [WinError 126] Не найден указанный модуль
В Notepad++ перевёл в UTF8 эту хрень:
РќРµ найден указанный модуль = Не найден указанный модуль
Т.е. он не находит твою dll-ку.

Скинь её сюда (неохота у себя Basic ставить), попробую из Блендера подключиться.
Название: Re: Запуск .dll из Python
Отправлено: Samovar от 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
Название: Re: Запуск .dll из Python
Отправлено: Striver от 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 появилось окошко.
Название: Re: Запуск .dll из Python
Отправлено: Samovar от 14 Декабрь 2016, 19:44:00
Ура, заработало! Понял где была ошибка. Спасибо огромное, Striver!
ПС. у меня кодировка на винде полетела... переустанавливать неохота... пырхался, пырхался, но так и не смог поправить... :(
Название: Re: Запуск .dll из Python
Отправлено: LanuHum от 14 Декабрь 2016, 19:55:26
Ура, заработало!

Ура! Спасибо, Striver, я бы не помог ему, у меня линукс.