PDA

Просмотр полной версии : [Вопрос] Вызов нативной функции



oukibt
26.02.2021, 17:41
Приветствую. Как я заметил, с нативными функциями дело обстоит немного не так, как с колбэками.
Функция amx_Exec работает неправильно на нативные функции. Как я понял, она(нативная функция) даже не вызывается, так как в аргумент
cell *retval возвращается мусорное значение.

У меня примерно такой код

if(amx_FindNative(this->info.amx, funcname, &idx) != AMX_ERR_NONE) return 0; // funcname = CreateDynamicObject

float value = 0.0;

amx_Push(this->info.amx, amx_ftoc(value)); // rz
amx_Push(this->info.amx, amx_ftoc(value)); // ry
amx_Push(this->info.amx, amx_ftoc(value)); // rx
amx_Push(this->info.amx, amx_ftoc(value)); // z
amx_Push(this->info.amx, amx_ftoc(value)); // y
amx_Push(this->info.amx, amx_ftoc(value)); // x

amx_Push(this->info.amx, static_cast<cell>(522)); // objectid

amx_Exec(this->info.amx, &ret_val, idx); // В ret_val возвращается мусорное значение.



Стример само собой подключен, функция используется 1 раз в OnGameModeInit() для того, чтобы плагин, соответственно, нашёл её.


Также есть второй вопрос. Какое предназначение имеет функция amx_Cleanup?

Daniel_Cortez
26.02.2021, 20:20
Функция amx_Exec работает неправильно на нативные функции.
Так она и не должна работать с нативными функциями, она предназначена только для public-функций. Нативные и public-функции находятся в разных таблицах и имеют раздельную нумерацию.

Остальное по нахождению и вызову нативок расписано здесь: https://pro-pawn.ru/showthread.php?14978&p=82762&viewfull=1#post82762

oukibt
27.02.2021, 13:53
Я установил себе модифицированную версию SDK, но здесь "func" не является членом класса, соответственно, возникает ошибка
https://cdn.discordapp.com/attachments/582915540285128725/815159160693325824/unknown.png
https://cdn.discordapp.com/attachments/582915540285128725/815159534595080202/unknown.png

Daniel_Cortez
27.02.2021, 19:19
Если немного напрячься и перейти к объявлению AMX_FUNCSTUB

http://ihost.pro-pawn.ru/image.php?di=XO55

typedef struct tagAMX_FUNCSTUB {
ucell address PACKED;
char name[sEXPMAX+1];
} AMX_FUNCSTUB;

то можно заметить поле "address" - это и есть адрес функции, нужно только привести его к типу AMX_NATIVE перед присвоением к func.

oukibt
28.02.2021, 10:37
С этим вроде разобрался, но я так и не получил ответ на главный вопрос, возможно, ошибка моя, и я неправильно донёс его суть.

Как вызвать из плагина функцию другого плагина? Я хочу получить что-то на подобии этого


cell idx;
if(amx_FindNative(amx, "DestroyDynamicObject", &idx) != AMX_ERR_NONE) return printf("Invalid native\n");
cell args[] = { 50 }, // id объекта
ret_value;
amx_CallNativeFunction(amx, idx, args, &ret_value);

Daniel_Cortez
28.02.2021, 11:44
Опять же, в посте по ссылке выше расписано всё по вызову нативок. На всякий случай я внёс в тот пост пару уточнений, но в целом всё то же самое.

oukibt
28.02.2021, 12:17
Так и не понял как это сделать. Поискал в интернете темы про вызов функций по адресу, получился вот такой код. Функция даже кое-как вызывалась, но я ловил ошибку.
"*** Streamer Plugin: DestroyDynamicObject: Expecting 1 parameter(s), but found 23237640."


native CallNative();

public OnGameModeInit()
{
CreateDynamicObject(50, 0, 0, 0, 0, 0, 0);
new id = CreateDynamicObject(50, 0, 0, 0, 0, 0, 0);
DestroyDynamicObject(id);
CallNative();
return 1;
}



cell AMX_NATIVE_CALL CallNative(AMX *amx, cell *params)
{
cell idx;
if (amx_FindNative(amx, "DestroyDynamicObject", &idx) != AMX_ERR_NONE) return printf("Invalid native\n");
AMX_HEADER *hdr = (AMX_HEADER*) amx->base;
AMX_FUNCSTUB *func_stub = GETENTRY(hdr, natives, idx);

typedef AMX_NATIVE func(cell);
func* DestroyDynamicObject = (func*)func_stub->address;
DestroyDynamicObject(1);
return 1;
}