Собираю экзешник для своего скрипта, используя py2exe.
Возникла следующая проблема:
есть у меня длл-ка, которую необходимо включить в собранный файл и использовать функции из неё, причем не распаковывая эту длл на жесткий диск. Т.е. нужно провернуть 3 действия в следующем порядке:
1. Добавить длл в exe как ресурс при сборке
2. Во время запуска exe загрузить длл из ресурсов в адресное пространство процесса и получить её handle
3. Передать полученный handle в функцию ctypes.WinDLL
Что мне удалось нарыть по каждому из “действий”:
1. Собственно это можно сделать, чем угодно. Например я сделал так:
autoitlib = open(".\AutoItX3.dll", "rb").read()
setup(
console = [{"script":"test.py", "other_resources":[(u"AUTOITX3.DLL", 1, autoitlib)]}],
)
2-3. Здесь заюзать ctype.LoadLibrary невозможно, т.к. она принимает только имя файла, поэтому придется использовать WinAPI как описано здесь:
http://www.py2exe.org/index.cgi/CustomDataInExe
В итоге имеем следующий скрипт для компиляции:
from ctypes import *
def GetModuleHandle(filename=None):
h=windll.kernel32.GetModuleHandleW(filename)
if not h:
raise WinError()
return h
def FindResource(typersc,idrsc,c_restype=c_char,filename=None):
if type(idrsc)is int:
idrsc='#%d'%idrsc
if type(typersc) is int:
typersc='#%d'%typersc
hmod=GetModuleHandle(filename)
print(hmod)
hrsc=windll.kernel32.FindResourceW(hmod,typersc,idrsc)
if not hrsc:
raise "111:" + str(WinError())
hglobal=windll.kernel32.LoadResource(hmod,hrsc)
if not hglobal:
raise WinError()
windll.kernel32.LockResource.restype=POINTER(c_restype)
return windll.kernel32.LockResource(hglobal)[0]
if __name__ == "__main__":
libhandle = FindResource(u"AUTOITX3.DLL", 1)
AutoIt = WinDLL(u"AUTOITX3.DLL", handle = libhandle)
111:[Error 1813] The specified resource type cannot be found in the image file."
hrsc=windll.kernel32.FindResourceW(hmod,typersc,idrsc)
P.S. Прикол в том, что нужный мне код есть в py2exe_util.pyd в функции load_resources, но по понятным причинам он не доступен.