Help JMP Hook (ffi)

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Автор темы
Друг
8,769
11,213
Версия MoonLoader
.026-beta
1. как в прототипе функции указать std::string?
2. как в прототипе функции указать "кастомный" (не ебу как это называется) тип данных? Например eSendrateType или dialogCallback_t

Вот пример функции: setSendRate(eSendrateType eType, int iValue);
 

RedHolms

Известный
Проверенный
617
360
1. как в прототипе функции указать std::string?
2. как в прототипе функции указать "кастомный" (не ебу как это называется) тип данных? Например eSendrateType или dialogCallback_t

Вот пример функции: setSendRate(eSendrateType eType, int iValue);
std::string можно передать как структуру (объявить typedef'ом структуру с идентичными полями, как и в string'е, и уже её передать), однако там есть свои подводные камни(copy-конструктор)

Кастомные типы можно объявлять обычным typedef:
Lua:
ffi.cdef[[
    typedef struct dummy {
        int something;
    } dummy_t;
    
    void Function(dummy_t)
]]
 

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Автор темы
Друг
8,769
11,213
std::string можно передать как структуру (объявить typedef'ом структуру с идентичными полями, как и в string'е, и уже её передать), однако там есть свои подводные камни(copy-конструктор)

Кастомные типы можно объявлять обычным typedef:
Lua:
ffi.cdef[[
    typedef struct dummy {
        int something;
    } dummy_t;
   
    void Function(dummy_t)
]]
Скрытое содержимое для пользователя(ей): RedHolms
 
  • Грустно
Реакции: qdIbp

RedHolms

Известный
Проверенный
617
360
*** Скрытый текст не может быть процитирован. ***
Сорян конечно, но тут я бессилен, плюсы под капотом оч сложная херня, тем более стандартная либа
Передать какой-либо класс можно, но это надо знатно так поебаться в жопу, учесть все конструкторы, деструкторы и т.п.
 
  • Грустно
Реакции: chapo

RedHolms

Известный
Проверенный
617
360
Пока занимался своим проектом, придумал идейку как это можно реализовать

Самый простой как по мне способ - сделать ддлку, в которой будет врапер для функции, например:
C++:
// исходная функций
int someFunction(std::string arg);

// врапер в ддлке
int someFunction_Wrapper(const char* arg) {
    return someFunction(std::string(arg));
}

Из под луа её уже можно будет вызвать:
Lua:
ffi = require 'ffi'

ffi.cdef[[
    int someFunction_Wrapper(const char* arg);
]]

local arg = 'Hello, World!'
local result = ffi.C.someFunction_Wrapper(arg)

Кто-то скажет костыль, но главное, что работает

Даже если тема не актуальна, всё равно)
 
  • Нравится
Реакции: The Spark

RTD

Нестандартное звание
Модератор
391
414
Передать какой-либо класс можно, но это надо знатно так поебаться в жопу, учесть все конструкторы, деструкторы и т.п.
std::string имеет такой вид
Lua:
typedef struct {
    union {
        char  szString[16];
        char *pszString;
    };
    int length;
    int allocated;
} stdstring;
Проблему создает только то, когда компилятор решает развернуть ее в пролог функции, а не передать по ссылке. Тогда получается такая примерно хрень, когда строка меньше 16 символов, то слишком костыльно можно достать, потому что ffi.string крашит, ffi.copy тоже не получается и я вижу только один способ как-то обработь такую строку лишь через tostring string:match и конкатеновать
Lua:
hk = function(this, a2, a3, a4, a5, lenght, allocated)
        if allocated < 16 then
            --как-то перевести a2 a3 a3 a4 a5 в единый char[16] для ffi.string
            --В консоле 1  |  a1 = 0x00000031    a2 a3 a4 a5 = NULL
            --11  | a1 = 0x00003131
            --1111 1111 | a1 = 0x31313131 a2 = 0x313131
            --0x31 => string.char(0x31) -> 1 (что и было введено)
            --string.char(ffi.cast("char*", a2)[0]) -> crash WTF???????
            sampAddChatMessage(("a2:%s | a3:%s | a4:%s | a5:%s"):format(a2, a3, a4, a5), 0x00DEAD)
        else
            sampAddChatMessage(ffi.string(a2), -1)
        end
        -- hk(this, a2, a3, a4, a5, lenght, allocated)
    end
    hk = hook.jmp.new("void(__thiscall*)(uintptr_t this, void* a2, void* a3, void* a4, void* a5, int lenght, int allocated)", hk, getModuleHandle("sampfuncs.asi") + 0x12482) --[[r1]]
Почему не сделать вместо void* a2, void* a3, void* a4, void* a5, int lenght, int allocated просто один параметр stdstring str - луа не понимает как этот прототип применить на луа функцию и крашится

А когда std::string передается по ссылке, то жить можно
Lua:
ffi.cdef[[
        typedef struct {
            union {
                char  szString[16];
                char *pszString;
            };
            int length;
            int allocated;
        } stdstring;
    ]]
    hk2 = function(this, str)
        sampAddChatMessage(ffi.string(str.allocated < 16 and str.szString or str.pszString), -1)
        --hk(this, str)
    end
    hk2 = hook.jmp.new("void(__thiscall*)(uintptr_t this, stdstring* str)", hk2, getModuleHandle("sampfuncs.asi") + 0x124D8) --r1
--r3 вроде 0x127B9
 
  • Нравится
Реакции: gaZmanoV и RedHolms