|
|
|
CreateThread блокирует ffi.C.Sleep |
|
|
DarkMaster |
1.6.2024, 17:23
|
Модератор UOPilot
Сообщений: 9.487
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 28025
Пользователь №: 11.279
|
code
Код local ffi = require("ffi")
ffi.cdef[[ typedef void* HANDLE; typedef void* HWND; typedef void* HINSTANCE; typedef unsigned int UINT; typedef int BOOL; typedef const char* LPCSTR; typedef long LONG; typedef unsigned int DWORD; typedef unsigned long long UINT_PTR; typedef void* LPVOID; typedef void* HMODULE; typedef int (__stdcall *THREAD_START_ROUTINE)(LPVOID lpThreadParameter); typedef UINT_PTR (__stdcall *TIMERPROC)(HWND, UINT, UINT_PTR, DWORD); typedef unsigned int WPARAM; typedef long LPARAM; typedef void* HFONT;
HWND __stdcall CreateWindowExA( LONG dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, LONG dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, void* hMenu, HINSTANCE hInstance, void* lpParam );
BOOL __stdcall ShowWindow( HWND hWnd, int nCmdShow );
BOOL __stdcall UpdateWindow( HWND hWnd );
int __stdcall MessageBoxTimeoutA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, UINT wLanguageId, UINT dwMilliseconds );
BOOL __stdcall DestroyWindow( HWND hWnd );
DWORD __stdcall GetCurrentThreadId();
HMODULE __stdcall GetModuleHandleA( LPCSTR lpModuleName );
HANDLE __stdcall CreateThread( void* lpThreadAttributes, size_t dwStackSize, THREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, DWORD* lpThreadId );
BOOL __stdcall CloseHandle( HANDLE hObject );
UINT_PTR __stdcall SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc );
BOOL __stdcall KillTimer( HWND hWnd, UINT_PTR uIDEvent );
typedef struct { int x; int y; } POINT;
typedef struct { HWND hwnd; UINT message; uintptr_t wParam; intptr_t lParam; DWORD time; POINT pt; } MSG;
typedef intptr_t LRESULT;
typedef struct { uint32_t size; uint32_t pos_x; uint32_t pos_y; uint32_t timeout; const char* text; } HintStruct;
BOOL __stdcall GetMessageA( MSG* lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax );
BOOL __stdcall TranslateMessage( const MSG* lpMsg );
LRESULT __stdcall DispatchMessageA( const MSG* lpMsg );
int __stdcall SendMessageA( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
HFONT __stdcall CreateFontA( int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, unsigned long fdwItalic, unsigned long fdwUnderline, unsigned long fdwStrikeOut, unsigned long fdwCharSet, unsigned long fdwOutputPrecision, unsigned long fdwClipPrecision, unsigned long fdwQuality, unsigned long fdwPitchAndFamily, LPCSTR lpszFace );
void Sleep(unsigned int dwMilliseconds);
static const int WM_SETFONT = 0x0030; ]]
local kernel32 = ffi.load("kernel32") local function createWindowAsync() ffi.cdef[[ void Sleep(unsigned int dwMilliseconds); ]] ffi.C.Sleep(1000) return 0 end
local function test() local threadId = ffi.new("DWORD[1]") local threadHandle = kernel32.CreateThread(nil, 0, ffi.cast("THREAD_START_ROUTINE", createWindowAsync), ffi.cast("LPVOID", 500), 0, threadId) kernel32.CloseHandle(threadHandle) end
while 1 do print"!!!!!!!!!!!!!" test() print(111) print(222) print(333) ffi.C.Sleep(1000) print"sleep end" end
Создавал окно, обратил внимание, что если окно еще живо, то вызов ffi.C.Sleep наглухо вешает основной поток. Обрезал код до минимума, чтобы воспроизводимость ошибки осталась. Так он еще и внутри нового потока стал с некоторым шансом забывать ffi.C.Sleep. Что не так?
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
DarkMaster |
2.6.2024, 2:34
|
Модератор UOPilot
Сообщений: 9.487
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 28025
Пользователь №: 11.279
|
ну так мы для этого и создаем поток. в одном потоке крутится окно и читаются сообщения, основной же поток встает на паузу. Причем даже если ты сделаешь вызов: while 1 do ffi.C.Sleep(1) -- 1 мс end что к локу привести не должно, темболее это основной поток в котором не находится окно, все равно все повиснет намертво. При этом если же вызвать слип, скажем на 10 секунд при существовании окна только 5 секунд, то лока не получится. Код который обрабатывал поток с окном был н<вырезано анти-матом>кирующем, окно не зависало. Так же обращаю внимание, что в текущем огрызке кода вообще никакие окна не создаются. Тупо создается новый поток, висит 1 секунду и завершается. При этом мы получаем какие-то дики ошибки, создается впечатление, что там что-то бьется и перезаписывается в памяти.
вобщем дальнейшие поиски оказались неожиданными. нитки безопасно из luajit не создаются. Для их создания в безопасном виде необходимо jit.off(). Так же функция которая передается, как инициализирующа не должна быть C функцией (возможно так же нельзя использовать далее по стеку C функции). Как альтернативу предлагали lua_newstate или как ее. Короче еще одну среду форкать из луа. Что-то в этом есть, это какой-то апогей всей структуры луа в котрой таблица в таблице в метатаблице, так еще и луа завернем в луа.
ну либо сторонние либы. в частности ты одну компилил =)
Сообщение отредактировал DarkMaster - 2.6.2024, 2:35
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
DarkMaster |
2.6.2024, 17:15
|
Модератор UOPilot
Сообщений: 9.487
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 28025
Пользователь №: 11.279
|
Вобщем как новый экземпляр со стринга стартнуть вроде разорался. А вот из существующей функции чет не пойму. Там вроде через lua_getfield надо. Сколько не крутил nil дергает. Пусть это тут отстанется - может пригодится. запуск отдельного экземпляра lua
Код local ffi = require 'ffi' local C = ffi.C ffi.cdef [[ typedef struct lua_State lua_State; lua_State *luaL_newstate(); void Sleep(unsigned int dwMilliseconds); void luaL_openlibs(lua_State *L); int luaL_loadstring (lua_State *L, const char *s); void lua_call (lua_State *L, int nargs, int nresults); ]]
-- Код передаваемый на исполнение local lua_code = [[ function my_function() local f = io.open("D:\\!IDDQD.txt", "wb+") f:close() print("Hello from Lua function!") end
my_function() ]]
-- Создаем новый объект состояния Lua local state = C.luaL_newstate() -- Загружаем стандартные либы io, math, string и т.д. C.luaL_openlibs(state) -- Загружаем код Lua C.luaL_loadstring(state, lua_code) C.lua_call(state, 0, 0)
C.Sleep(10000)
Сообщение отредактировал DarkMaster - 2.6.2024, 17:18
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
DarkMaster |
2.6.2024, 17:42
|
Модератор UOPilot
Сообщений: 9.487
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 28025
Пользователь №: 11.279
|
создаем экзепляр из готовой lua функции
Код local ffi = require 'ffi' local C = ffi.C ffi.cdef [[ typedef struct lua_State lua_State; lua_State *luaL_newstate(); void Sleep(unsigned int dwMilliseconds); void luaL_openlibs(lua_State *L); void lua_call (lua_State *L, int nargs, int nresults); typedef int (*lua_CFunction)(lua_State *L); void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); ]]
local f = function() print"Where am i?" local f = io.open("D:\\!IDDQD.txt", "wb+") f:close() return 0 -- Вернуться должен 0, иначе error кинет. end
-- Создаем новый объект состояния Lua local state = C.luaL_newstate() -- Пушим функцию C.lua_pushcclosure (state, f, 0) -- Загружаем стандартные либы io, math, string и т.д. C.luaL_openlibs(state) -- Выполняем функцию C.lua_call(state, 0, 0)
C.Sleep(10000) Цитата Совета не спрашивали, но имхо - зачем возиться с окнами (первоначальная задача вроде в них) на голом вин апи ? намного приятнее взять delphi/c# и сделать приложение, которое по запросам через tcp будет делать что нужно, и уведомлять скрипты на луа, + интерфейсы куда мощнее возможно делать, а не 105 вызовов на рисование пустой кнопки в вин апи Я тупо хотел хинт оживить, а тут вон как получилось. Я грешным делом уже смотрел на iup, wx и вспоминал твои слова, что не нужно трогать интерфесы пилота и делать, то, что уже сделано ибо там пропадешь с концами. Сообщение отредактировал DarkMaster - 2.6.2024, 17:46
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
DarkMaster |
2.6.2024, 21:58
|
Модератор UOPilot
Сообщений: 9.487
Регистрация: 2.12.2008 Группа: Супермодераторы Наличность: 28025
Пользователь №: 11.279
|
подгружать через require вызов: Код local hint = require"hint" hint(text, size, pos_x, pos_y, width, height, timeout)
В рамках пилота есть особенность - окно хинта закроется только после таймаута, даже если скрипт уже остановлен. Особенности реализации пилота. В чистом луа такого поведения нет. hint
Код --lua local ffi = require 'ffi' local C = ffi.C ffi.cdef [[ typedef struct lua_State lua_State; lua_State *luaL_newstate(); void Sleep(unsigned int dwMilliseconds); void luaL_openlibs(lua_State *L); int luaL_loadstring (lua_State *L, const char *s); void lua_call (lua_State *L, int nargs, int nresults); ]]
local lua_code = [=====[ local mega_f = function(...) local ffi = require("ffi") local C = ffi.C
ffi.cdef[[ typedef void* HANDLE; typedef void* HWND; typedef void* HINSTANCE; typedef unsigned int UINT; typedef int BOOL; typedef const char* LPCSTR; typedef long LONG; typedef unsigned int DWORD; typedef unsigned long long UINT_PTR; typedef void* LPVOID; typedef void* HMODULE; typedef int (__stdcall *THREAD_START_ROUTINE)(LPVOID lpThreadParameter); typedef UINT_PTR (__stdcall *TIMERPROC)(HWND, UINT, UINT_PTR, DWORD); typedef unsigned int WPARAM; typedef long LPARAM; typedef void* HFONT;
HWND __stdcall CreateWindowExA( LONG dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, LONG dwStyle, int x, int y, int nWidth, int nHeight, HWND hWndParent, void* hMenu, HINSTANCE hInstance, void* lpParam );
BOOL __stdcall ShowWindow( HWND hWnd, int nCmdShow );
BOOL __stdcall UpdateWindow( HWND hWnd );
int __stdcall MessageBoxTimeoutA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType, UINT wLanguageId, UINT dwMilliseconds );
BOOL __stdcall DestroyWindow( HWND hWnd );
DWORD __stdcall GetCurrentThreadId();
HMODULE __stdcall GetModuleHandleA( LPCSTR lpModuleName );
HANDLE __stdcall CreateThread( void* lpThreadAttributes, size_t dwStackSize, THREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, DWORD* lpThreadId );
BOOL __stdcall CloseHandle( HANDLE hObject );
UINT_PTR __stdcall SetTimer( HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc );
BOOL __stdcall KillTimer( HWND hWnd, UINT_PTR uIDEvent );
typedef struct { int x; int y; } POINT;
typedef struct { HWND hwnd; UINT message; uintptr_t wParam; intptr_t lParam; DWORD time; POINT pt; } MSG;
typedef intptr_t LRESULT;
typedef struct { uint32_t size; uint32_t pos_x; uint32_t pos_y; uint32_t width; uint32_t height; uint32_t timeout; const char* text; } HintStruct;
BOOL __stdcall GetMessageA( MSG* lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax );
BOOL __stdcall TranslateMessage( const MSG* lpMsg );
LRESULT __stdcall DispatchMessageA( const MSG* lpMsg );
int __stdcall SendMessageA( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
HFONT __stdcall CreateFontA( int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, unsigned long fdwItalic, unsigned long fdwUnderline, unsigned long fdwStrikeOut, unsigned long fdwCharSet, unsigned long fdwOutputPrecision, unsigned long fdwClipPrecision, unsigned long fdwQuality, unsigned long fdwPitchAndFamily, LPCSTR lpszFace );
void Sleep(unsigned int dwMilliseconds);
static const int WM_SETFONT = 0x0030;
typedef struct lua_State lua_State; lua_State *luaL_newstate(); void Sleep(unsigned int dwMilliseconds); void luaL_openlibs(lua_State *L); void lua_call (lua_State *L, int nargs, int nresults); typedef int (*lua_CFunction)(lua_State *L); void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); ]]
local user32 = ffi.load("user32") local kernel32 = ffi.load("kernel32") local Gdi32 = ffi.load("Gdi32.dll") local sleep = C.Sleep
-- Переменная для хранения дескриптора окна с сообщением local previousMessageWindow = nil
local function createWindow(HintStruct) local hwnd = user32.CreateWindowExA( 0, -- dwExStyle "STATIC" , -- lpClassName HintStruct.text, -- lpWindowName 0x80000000, -- dwStyle WS_POPUP HintStruct.pos_x, -- x HintStruct.pos_y, -- y HintStruct.width, -- nWidth HintStruct.height,-- nHeight nil, -- hWndParent nil, -- hMenu nil, -- hInstance nil -- lpParam )
-- Создаем шрифт local hFont = Gdi32.CreateFontA( HintStruct.size, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, "Arial" )
-- Устанавливаем шрифт local res = user32.SendMessageA(hwnd, C.WM_SETFONT, ffi.cast("WPARAM", hFont), 1)
user32.ShowWindow(hwnd, 5) -- SW_SHOW user32.UpdateWindow(hwnd)
return hwnd end
local function createTimer(hwnd, timeout) local timerId = user32.SetTimer(hwnd, 1, timeout, nil) return timerId end
local function destroyTimer(hwnd, timerId) user32.KillTimer(hwnd, timerId) end
local function createWindowAsync(HintStruct) HintStruct = ffi.cast("HintStruct*", HintStruct) -- Если предыдущее окно существует, закрываем его if previousMessageWindow ~= nil then print"_____" user32.DestroyWindow(previousMessageWindow) print"XXXX" previousMessageWindow = nil end
local hwnd = createWindow(HintStruct)
-- Сохраняем дескриптор текущего окна как предыдущий previousMessageWindow = hwnd
if hwnd ~= nil then local timerId = createTimer(hwnd, HintStruct.timeout) -- Set timer for specified timeout
-- Н<вырезано анти-матом>кирующее ожидание событий окна local start = os.clock() while os.clock() - start < HintStruct.timeout / 1000 do local msg = ffi.new("MSG") local result = user32.GetMessageA(msg, nil, 0, 0) if type(result) == 'number' and result > 0 then user32.TranslateMessage(msg) user32.DispatchMessageA(msg) end end
destroyTimer(hwnd, timerId) -- Destroy timer user32.DestroyWindow(hwnd) -- Destroy window
-- Обнуляем дескриптор предыдущего окна, так как оно уже было закрыто previousMessageWindow = nil else print("Failed to create window") end
return 0 end
local function hint(text, size, pos_x, pos_y, width, height, timeout) print(text) print(size) print(pos_x) local HintStruct = ffi.new("HintStruct") HintStruct.text = text HintStruct.size = size HintStruct.pos_x = pos_x HintStruct.pos_y = pos_y HintStruct.width = width HintStruct.height = height HintStruct.timeout = timeout local threadId = ffi.new("DWORD[1]") local threadHandle = kernel32.CreateThread(nil, 0, ffi.cast("THREAD_START_ROUTINE", createWindowAsync), ffi.cast("LPVOID", HintStruct), 0, threadId) kernel32.CloseHandle(threadHandle) return 0 end
]=====]
local create_state = function(text, size, pos_x, pos_y, width, height, timeout) local text = text and tostring(text) or "text" local size = size or 24 local pos_x = pos_x or 0 local pos_y = pos_y or 0 local width = width or 400 local height = height or 200 local timeout = timeout or 5000
print(text) print([[hint(']].. text.."', "..size..", ".. pos_x..", "..pos_y..", ".. width..", "..height..", ".. timeout)
-- Создаем новый объект состояния Lua local state = C.luaL_newstate() -- Загружаем стандартные либы io, math, string и т.д. C.luaL_openlibs(state) -- Загружаем код Lua C.luaL_loadstring(state, lua_code..[[hint(']].. text.."', "..size..", ".. pos_x..", "..pos_y..", ".. width..", "..height..", ".. timeout..[[) return 0 end mega_f()]]) C.lua_call(state, 0, 0)
return 0 end
return create_state По созданию нового state. Если передавать уже готовые функции, то весь набор проблем никуда не денется. Пришлось текстом код пушить...
--------------------
Скрипты UOPilot под заказ. Консультации по UOpilot 15$/час. Услуги Lua разработчика (не пилот, проекты, постоянка) Disсоrd: Kov____
|
|
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|