Исходник Гайд AHK-LUA-API

#Rin

Известный
Автор темы
Всефорумный модератор
1,214
1,035
AHK-LUA-API
API для взаимодействия LUA и AHK.
API состоит из файла AHK-LUA-API.ahk, для работы требуется lua51.dll.
Для подключения библиотеки нужно вписать в начало скрипта следующий код:
AutoHotKey:
#include AHK-LUA-API.ahk
Перед тем как вызывать функции нужно подгрузить lua51.dll в процесс ахк.
AutoHotKey:
DllCall("kernel32.dll\LoadLibrary", "Str", A_ScriptDir "\lua51.dll")


Примеры:
Вызов AHK функции из Lua:
AutoHotKey:
L := luaL_newstate()
lua_register(L, "MsgBox", "LUAFUNC_MsgBox")
lua_register(L, "Test", "LUAFUNC_Test")

code =
(
    sum = Test(228, 1337, 666)
    MsgBox("sum = " .. sum)
)

luaL_doString(L, code)
lua_close(L)

LUAFUNC_MsgBox(L)
{
    MsgBox, % lua_tostring(L, 1)
    return 0
}

LUAFUNC_Test(L)
{
    sum := 0
    n := lua_gettop(L)
    loop % n
        sum += lua_tonumber(L, A_Index)
    lua_pushnumber(L, sum)
    return 1
}
Вызов Lua функции из AHK:
AutoHotKey:
L := luaL_newstate()

code =
(
    function add(x, y)
        return x + y
    end
)

luaL_doString(L, code)
MsgBox, % LUAFUNC_add(L, 5, 13)
lua_close(L)

LUAFUNC_add(L, x, y)
{
   lua_getglobal(L, "add")
   lua_pushnumber(L, x)
   lua_pushnumber(L, y)
   lua_call(L, 2, 1)
   sum := lua_tointeger(L, -1)
   lua_pop(L, 1)
   return sum
}
Чтение Lua переменных:
AutoHotKey:
L := luaL_newstate()

code =
(
    var = "String"
)

luaL_doString(L, code)

lua_getglobal(L, "var")
MsgBox, % lua_tostring(L, -1)

lua_close(L)
Активация функции на клавишу, через AHK:
AutoHotKey:
L := luaL_newstate()

lua_register(L, "MsgBox", "LUAFUNC_MsgBox")
lua_register(L, "Hotkey", "LUAFUNC_Hotkey")

code =
(
    Hotkey("!1", "Show", "On")
    function Show(ThisHotKey)
        MsgBox("ThisHotKey = " .. ThisHotKey)
    end
)

luaL_doString(L, code)

LUAFUNC_MsgBox(L)
{
    MsgBox, % lua_tostring(L, 1)
    return 0
}

LUAFUNC_Hotkey(L)
{
    static HotKeyCount := 0, ARGS := {}
    ARGS.Push({L: L, ARG1: lua_tostring(L, 1), ARG2: lua_tostring(L, 2), ARG3: lua_tostring(L, 3)})
    HotKeyCount++
    Hotkey, % ARGS[HotKeyCount]["ARG1"], LuaHotKey, % ARGS[HotKeyCount]["ARG3"]
    lua_pushnumber(L, ErrorLevel)
    return 1

    LuaHotKey:
        for k, v in ARGS
        {
            if (A_ThisHotkey == v["ARG1"])
            {
                lua_getglobal(v["L"], v["ARG2"])
                lua_pushstring(v["L"], A_ThisHotkey)
                lua_call(v["L"], 1, 0)
            }
        }
    return
}
Экспорты луа апи генерируются автоматический:
AutoHotKey:
result = ; Переменная в которую будеть писаться сгенерирвованный код.
(
/*
    AHK-LUA-API

    MIT License

    Copyright (c) 2018 Rinat_Namazov

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
*/

global LUAJIT_MODE_ENGINE        := 0    ; Set mode for whole JIT engine.
global LUAJIT_MODE_DEBUG        := 1    ; Set debug mode (idx = level).
global LUAJIT_MODE_FUNC            := 2    ; Change mode for a function.
global LUAJIT_MODE_ALLFUNC        := 3    ; Recurse into subroutine protos.
global LUAJIT_MODE_ALLSUBFUNC    := 4    ; Change only the subroutines.
global LUAJIT_MODE_TRACE        := 5    ; Flush a compiled trace.
global LUAJIT_MODE_WRAPCFUNC    := 0x10 ; Set wrapper mode for C function calls.
global LUAJIT_MODE_MAX
global LUA_TNONE                := -1
global LUA_TNIL                    := 0
global LUA_TBOOLEAN                := 1
global LUA_TLIGHTUSERDATA        := 2
global LUA_TNUMBER                := 3
global LUA_TSTRING                := 4
global LUA_TTABLE                := 5
global LUA_TFUNCTION            := 6
global LUA_TUSERDATA            := 7
global LUA_TTHREAD                := 8
global LUA_REGISTRYINDEX        := -10000
global LUA_ENVIRONINDEX            := -10001
global LUA_GLOBALSINDEX            := -10002
global BUFSIZ                    := 512
global LUAL_BUFFERSIZE            := (BUFSIZ > 16384 ? 8192 : BUFSIZ)
global LUA_GCSTOP                := 0
global LUA_GCRESTART            := 1
global LUA_GCCOLLECT            := 2
global LUA_GCCOUNT                := 3
global LUA_GCCOUNTB                := 4
global LUA_GCSTEP                := 5
global LUA_GCSETPAUSE            := 6
global LUA_GCSETSTEPMUL            := 7

lua_pop(ByRef L, n)
{
    lua_settop(L, -n - 1)
}

lua_newtable(ByRef L)
{
    return lua_createtable(L, 0, 0)
}

lua_register(ByRef L, n, f)
{
    if f is not integer
        f := RegisterCallback(f, "CDecl")
    lua_pushcfunction(L, f)
    lua_setglobal(L, n)
}

lua_pushcfunction(ByRef L, f)
{
    return lua_pushcclosure(L, f, 0)
}

lua_strlen(ByRef L, i)
{
    return lua_objlen(L, i)
}

lua_isfunction(ByRef L, n)
{
    return (lua_type(L, n) == LUA_TFUNCTION)
}

lua_istable(ByRef L, n)
{
    return (lua_type(L, n) == LUA_TTABLE)
}

lua_islightuserdata(ByRef L, n)
{
    return (lua_type(L, n) == LUA_TLIGHTUSERDATA)
}

lua_isnil(ByRef L, n)
{
    return (lua_type(L, n) == LUA_TNIL)
}

lua_isboolean(ByRef  L, n)
{
    return (lua_type(L, n) == LUA_TBOOLEAN)
}

lua_isthread(ByRef  L, n)
{
    return (lua_type(L, n) == LUA_TTHREAD)
}

lua_isnone(ByRef L, n)
{
    return (lua_type(L, n) == LUA_TNONE)
}

lua_isnoneornil(ByRef L, n)
{
    return (lua_type(L, n) <= 0)
}

lua_pushliteral(ByRef L, s)
{
    return lua_pushlstring(L, s, strlen(s))
}

lua_setglobal(ByRef L, s)
{
    return lua_setfield(L, LUA_GLOBALSINDEX, s)
}

lua_getglobal(ByRef L, s)
{
    return lua_getfield(L, LUA_GLOBALSINDEX, s)
}

lua_tostring(ByRef L, i)
{
    return lua_tolstring(L, i, 0)
}

lua_open()
{
    return luaL_newstate()
}

lua_getregistry(ByRef L)
{
    return lua_pushvalue(L, LUA_REGISTRYINDEX)
}

lua_getgccount(ByRef L)
{
    return lua_gc(L, LUA_GCCOUNT, 0)
}

lua_upvalueindex(i)
{
    return LUA_GLOBALSINDEX - i
}

luaL_dofile(ByRef L, fn)
{
    luaL_loadfile(L, fn)
    return lua_pCall(l, 0, -1, 0)
}

luaL_dostring(ByRef L, ByRef s)
{
    luaL_loadstring(L, s)
    return lua_pCall(L, 0, -1, 0)
}
)
AutoHotKey:
GetType(type, isRetVal := false)
{
    types := { "lua_State": "Ptr"
        , "int": "Int"
        , "size_t": "Int"
        , "const char": "Str"
        , "lua_Integer": "Int"
        , "lua_Number": "Double" }
    if (isRetVal && type == "void")
        return ""
    if (types[type] != "")
        return (isRetVal ? " " : "") types[type]
    return (isRetVal ? " " : "") "UInt" ; const luaL_Reg, luaL_Buffer, lua_Alloc, lua_CFunction, const lua_Debug, lua_Debug, lua_Hook, lua_Reader, lua_Writer
}
FuncList := ["LUAJIT_VERSION_SYM"]

Loop, LuaJIT-master\src\*.c ; Проходимся по всем файлам с расширением ".c" исходника LuaJIT.
{
    A_FileText := "", fpos := 1 ; Позиция с которого начинается поиск по шаблону.
    Loop, Read, %A_LoopFileFullPath% ; Читаем построчно файл.
    {
        TrimLine := Trim(A_LoopReadLine) ; Убираем лишние символы (\n|\r|\s|\t).
        if (TrimLine != "") ; Если строка не пустая.
            A_FileText .= TrimLine ; Добавляем строку без переноса.
    }
    while (npos := RegExMatch(A_FileText, "mUS)(LUALIB_API|LUA_API)\s(?<Type>[a-zA-Z0-9_\s]+)\s(?<IsPtrOrAddrOrDefault>[*&]{0,1})(?<Name>[a-zA-Z0-9_]+)\((?<Params>.*)\)", Func_, fpos)) ; Поиск функций.
    {
        fpos := npos + strlen(Func_) ; Прибавляем к позиции длину вхождения.
        IsContinue := false
        for k, v in FuncList ; Поиск функции, вдруг она уже найдена.
        {
            if (Func_Name == v)
                IsContinue := true ; Функция найдена.
        }
        if (IsContinue) ; Если функция уже найдена.
            continue ; Пропускаем.
        AhkFuncParams := "", DllCallParams := "" ; Будущие аргументы.
        if (Func_Params != "void") ; Если функция имеет аргументы.
        {
            Loop, Parse, % Func_Params, `, ; Проходимся по аргументам функции.
            {
                RegExMatch(Trim(A_LoopField), "S)(?<Type>[a-zA-Z0-9_\s]+)\s(?<IsPtrOrAddrOrDefault>[*&]{0,2})(?<Name>[a-zA-Z0-9_]+)", Params_) ; Делим аргумент на тип и название.
                if (Params_Type == "va_list" || A_LoopField == " ...") ; Пропускаем, ведь ахк само умеет форматировать.
                    continue
                if (Params_Name == "l") ; Так как AHK не регистрозависимый язык, нужно заменить.
                    Params_Name := "l2"
                AhkFuncParams .= (A_Index == 1 ? "" : ", ") (Params_IsPtrOrAddrOrDefault == "*" ? "ByRef " : "") Params_Name ; Аргументы в ахк функцию.
                DllCallParams .= (A_Index == 1 ? "" : ", ") """" GetType(Params_Type) """, " Params_Name ; Аргументы в С функцию.
            }
        }
        FuncList.Push(Func_Name) ; Добавляем функцию в список.
        result .= "`n`n" Func_Name "(" AhkFuncParams ")`n{`n`treturn DllCall(""lua51.dll\" Func_Name """" (DllCallParams == "" ? "" : ", " DllCallParams) ", ""CDecl" GetType(Func_Type, true) """)`n}" ; Формируем код.
    }
}

FileDelete, AHK-LUA-API.ahk
FileAppend, %result%, AHK-LUA-API.ahk
 

Вложения

  • AHK-LUA-API.zip
    10 KB · Просмотры: 107
Последнее редактирование:

AnWu

Guardian of Order
Всефорумный модератор
4,683
5,128
какой в этом смысл?
все равно что писать письмо в письме. вообще не вижу в этом логики, еще и скорость луа умирает из-за ахк.
 

Frapsy

Известный
Проверенный
393
226
Ты конечно вложил в это свои силы, но рил, в чем кайф таких извращений, если проще уж начать писать на LUA? Это логичней и правильней будет, нежели мутить между этими двумя созданиями API для извращений.
 

iAmerican

Известный
Друг
615
257
какой в этом смысл?
все равно что писать письмо в письме. вообще не вижу в этом логики, еще и скорость луа умирает из-за ахк.
Ты конечно вложил в это свои силы, но рил, в чем кайф таких извращений, если проще уж начать писать на LUA? Это логичней и правильней будет, нежели мутить между этими двумя созданиями API для извращений.
Потому что может, по этому и создает.
Такие работы , как по мне , уникальны.
 

cover

Известный
Проверенный
245
273
Потому что может, по этому и создает.
Такие работы , как по мне , уникальны.
Несомненно, была проделана определенная работа и это должно ценится, но вопрос в другом: насколько это полезно?
 
  • Нравится
Реакции: imring

ЯedЯuM

Malware Maker
244
304
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Несомненно, была проделана определенная работа и это должно ценится, но вопрос в другом: насколько это полезно?
Я не смотрел апи но если он добавил весь функционал lua51.dll то можно ставить дебаг хуки на луа скрипты и отслеживать значения всех переменных и вызовы функций, полезно для обхода привязок в закомпилированых скриптах.
 
  • Нравится
Реакции: Kvisk и AnWu

#Rin

Известный
Автор темы
Всефорумный модератор
1,214
1,035
Я не смотрел апи но если он добавил весь функционал lua51.dll
Да.
то можно ставить дебаг хуки на луа скрипты и отслеживать значения всех переменных и вызовы функций, полезно для обхода привязок в закомпилированых скриптах.
lua_sethook(L, func, mask, count)

Устанавливает функцию отладочной ловушки (hook).

Аргумент func является функцией ловушки. mask указывает на каких событиях будет вызываться ловушка: значение аргумента формируется побитовым ИЛИ из констант LUA_MASKCALL, LUA_MASKRET, LUA_MASKLINE, и LUA_MASKCOUNT. Аргумент count имеет смысл только когд маска содержит LUA_MASKCOUNT. Для каждого события, ловушка вызывается как описано ниже:
  • Ловушка вызова: вызывается, когда интерпретатор вызывает функцию. Ловушка вызывается сразу после ввода Lua новой функции, перед получением функцией своих аргументов.
  • Ловушка возврата: вызывается когда интерпретатор возвращается из функции. Ловушка вызывается непосредственно перед тем, как Lua оставляет функцию. При этом нет стандартного способа обращения к значениям, возвращаемым функцией.
  • Ловушка строки: вызывается когда интерпретатор собирается начать выполнение новой строки кода или когда он переходит назад в коде (даже на ту же самую строку). (Это событие происходит только пока Lua выполняет Lua функцию.)
  • Ловушка счета: вызывается после выполнения интерпретатором каждого определенного количества (указанного в count) инструкций. (Это событие происходит только пока Lua выполняет Lua функцию.)
Ловушка отключается установкой аргумента mask в ноль.

Но нужно знать указатель на структуру интерпретатора который в MoonLoader используется. Либо погуглю про апи, вдруг там есть функция для получения, либо в отладчике поставлю хук на luaL_newstate и вернувшись из функции узнаю адрес с указателем.
 
Последнее редактирование:
  • Нравится
Реакции: ЯedЯuM

cover

Известный
Проверенный
245
273
Я не смотрел апи но если он добавил весь функционал lua51.dll то можно ставить дебаг хуки на луа скрипты и отслеживать значения всех переменных и вызовы функций, полезно для обхода привязок в закомпилированых скриптах.
Как будто это нельзя сделать через другой луа скрипт.
 

AnWu

Guardian of Order
Всефорумный модератор
4,683
5,128
Я все еще не вижу в этом смысла. Ковер везде прав. Можно было и более полезно провести время. Да даже время потраченное на порнхаб в разы кпдшней
 

cover

Известный
Проверенный
245
273
Это определенно круто, что ты сделал подобное, но надо учитывать тот факт, что чем проще - тем лучше. Но для людей, которые любят писать на АХК, будет полезно.
 

madrasso

Потрачен
883
323
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Это определенно круто, что ты сделал подобное, но надо учитывать тот факт, что чем проще - тем лучше. Но для людей, которые любят писать на АХК, будет полезно.
Люди которые пишут на ахк (а точнее самперы), не смогут осилить подобное, только единицы.
 
  • Нравится
Реакции: Emilio Armstrong

project0

Новичок
5
0
@Rinat_Namazov, если не сложно, был бы очень благодарен за ссылку на проект на AHK-LUA-API со скриптом который выводит что-либо в игровой чат. Чет вообще недоумеваю как это должно работать, lua51.dll подгружается и MsgBox выводит, и на этом, как говорится, всё, и ещё - где можно взять нормальную библиотеку для LUA?
 

Double Tap Inside

Известный
Проверенный
1,897
1,245
Ебать, так это охуенно, блять.

Ток это... Я вот хочу написать функцию в .ahk и вызвать её уже из .lua
Чет не вьебу, даже как примеры запустить.
Кинул Апи и примеры в папку GTA там же и lua51.dll валяется.
чет нихуя я понять не могу

"Экспорты луа апи генерируются автоматический:" - а это шо и куда?

---
есть какие - то публичные пирмеры скриптов на ahk и на lua использующие это API?
 
Последнее редактирование: