Для этого нужна обычная библиотека DLL, подключаемая к QLua, о том, как ее создать можете посмотреть здесь.
Пусть созданная Вами DLL называется "LuaCallback.dll", которая находится в корневом каталоге терминала QUIK.
Следующий пример 10 раз, с периодичностью в 1 секунду выведет сообщение с текстом "Привет из DLL" посредством вызова из DLL функции из Qlua скрипта MyLuaCallback():
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | require("LuaCallback"); -- Подключает библиотеку "LuaCallback.dll" Run = true; -- Флаг поддержания работы скрипта -- Основная функция скрипта, пока работает она, работает скрипт function main() LuaCallback.StartCallback(); -- Запускает механизм вызова функции MyLuaCallback из DLL while Run do sleep(1000); end; -- Поддерживает работу скрипта end; -- Функция, вызываемая из DLL function MyLuaCallback(Text) message(Text); -- Выводит сообщение, переданное в функцию из DLL end; -- Функция завершения работы скрипта function OnStop() Run = false; -- Завершает цикл while, следовательно завершается main() и сам скрипт останавливается end; |
require("LuaCallback"); -- Подключает библиотеку "LuaCallback.dll" Run = true; -- Флаг поддержания работы скрипта -- Основная функция скрипта, пока работает она, работает скрипт function main() LuaCallback.StartCallback(); -- Запускает механизм вызова функции MyLuaCallback из DLL while Run do sleep(1000); end; -- Поддерживает работу скрипта end; -- Функция, вызываемая из DLL function MyLuaCallback(Text) message(Text); -- Выводит сообщение, переданное в функцию из DLL end; -- Функция завершения работы скрипта function OnStop() Run = false; -- Завершает цикл while, следовательно завершается main() и сам скрипт останавливается end;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #include <windows.h> //Подключает все необходимое #include <thread> //Подключает возможность работы с потоками //=== Необходимые для Lua константы ============================================================================// #define LUA_LIB #define LUA_BUILD_AS_DLL //=== Заголовочные файлы LUA ===================================================================================// extern "C" { #include "Lua\lauxlib.h" #include "Lua\lua.h" } //=== Стандартная точка входа для DLL ==========================================================================// BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } //Функция вызывает функцию из QLua с периодичностью в 1 секунду static int MyCallback(lua_State *L) { lua_getglobal(L, "MyLuaCallback"); //Находит в стеке Lua функцию по ее названию и помещает ее наверх стека int callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); //Получает индекс функции в специальной внутренней таблице(реестре) Lua for (int i = 0; i < 10;i++) { lua_rawgeti(L, LUA_REGISTRYINDEX, callbackRef); //Достает функцию из реестра Lua по индексу и помещает в стек lua_pushstring(L, "Привет из DLL"); //Добавляет в стек параметр, который будет передан функции lua_call(L, 1, 1); //Вызывает выбранную функцию в скрипте QLua, передавая в нее 1 параметр (L - стек, 1 - количество передаваемых параметров, 1 - количество возвращаемых значений(нужно, чтобы обновлять стек)) Sleep(1000); //Пауза в 1 секунду } return 0; //Выход из функции } //=== Реализация функций, вызываемых из LUA ====================================================================// static int forLua_StartCallback(lua_State *L) { std::thread thr(MyCallback, L); //Запускает выполнение функции MyCallback() в отдельном потоке thr.detach(); //Отсоединяет созданный поток от основного, делая его "фоновым" return (0); //Завершает работу функции forLua_StartCallback, при этом функция MyCallback продолжает работать в отдельном потоке } //=== Регистрация реализованных в dll функций, чтобы они стали "видимы" для Lua ================================// static struct luaL_reg ls_lib[] = { { "StartCallback", forLua_StartCallback } }; //=== Регистрация названия библиотеки, видимого в скрипте Lua ==================================================// extern "C" LUALIB_API int luaopen_LuaCallback(lua_State *L) { luaL_openlib(L, "LuaCallback", ls_lib, 0); return 0; } |
#include <windows.h> //Подключает все необходимое #include <thread> //Подключает возможность работы с потоками //=== Необходимые для Lua константы ============================================================================// #define LUA_LIB #define LUA_BUILD_AS_DLL //=== Заголовочные файлы LUA ===================================================================================// extern "C" { #include "Lua\lauxlib.h" #include "Lua\lua.h" } //=== Стандартная точка входа для DLL ==========================================================================// BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { return TRUE; } //Функция вызывает функцию из QLua с периодичностью в 1 секунду static int MyCallback(lua_State *L) { lua_getglobal(L, "MyLuaCallback"); //Находит в стеке Lua функцию по ее названию и помещает ее наверх стека int callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); //Получает индекс функции в специальной внутренней таблице(реестре) Lua for (int i = 0; i < 10;i++) { lua_rawgeti(L, LUA_REGISTRYINDEX, callbackRef); //Достает функцию из реестра Lua по индексу и помещает в стек lua_pushstring(L, "Привет из DLL"); //Добавляет в стек параметр, который будет передан функции lua_call(L, 1, 1); //Вызывает выбранную функцию в скрипте QLua, передавая в нее 1 параметр (L - стек, 1 - количество передаваемых параметров, 1 - количество возвращаемых значений(нужно, чтобы обновлять стек)) Sleep(1000); //Пауза в 1 секунду } return 0; //Выход из функции } //=== Реализация функций, вызываемых из LUA ====================================================================// static int forLua_StartCallback(lua_State *L) { std::thread thr(MyCallback, L); //Запускает выполнение функции MyCallback() в отдельном потоке thr.detach(); //Отсоединяет созданный поток от основного, делая его "фоновым" return (0); //Завершает работу функции forLua_StartCallback, при этом функция MyCallback продолжает работать в отдельном потоке } //=== Регистрация реализованных в dll функций, чтобы они стали "видимы" для Lua ================================// static struct luaL_reg ls_lib[] = { { "StartCallback", forLua_StartCallback } }; //=== Регистрация названия библиотеки, видимого в скрипте Lua ==================================================// extern "C" LUALIB_API int luaopen_LuaCallback(lua_State *L) { luaL_openlib(L, "LuaCallback", ls_lib, 0); return 0; }
Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!