PDA

Просмотр полной версии : [Вопрос] sampgdk::FindNative



Batya_Montes
01.01.2019, 19:40
Привет, собственно интересует вот такой вопросик. Есть функция вызывающая CreateDynamicPickupEx из плагина написанная на sampgdk.
int NLCallNative::CreateDynamicPickupEx(int modelid, int type, float x, float y, float z, float streamdistance, const int worlds[], const int interiors[], const int players[],
const int areas[], int priority, int maxworlds, int maxinteriors, int maxplayers, int maxareas)
{
static AMX_NATIVE Native = sampgdk::FindNative("CreateDynamicPickupEx");
std::string function_format = std::string("iiffffa[") + std::to_string(maxworlds) + std::string("]a[") + std::to_string(maxinteriors) + std::string("]a[")
+ std::to_string(maxplayers) + std::string("]a[") + std::to_string(maxareas) + std::string("]iiiii");
if (Native != NULL) return sampgdk::InvokeNative(Native, function_format.c_str(), modelid, type, x, y, z, streamdistance, worlds, interiors, players, areas,
priority, maxworlds, maxinteriors, maxplayers, maxareas);
return 0;
}

Так же есть хук на эту самую нативку - CreateDynamicPickupEx.
cell AMX_NATIVE_CALL HookedNatives::acc_CreateDynamicPickupEx(AMX * amx, cell * params)
{
int ac_pickupid = NLCallNative::CreateDynamicPickupEx(params[1], params[2], amx_ctof(params[3]), amx_ctof(params[4]), amx_ctof(params[5]), amx_ctof(params[6]),
reinterpret_cast<int *> (params[7]), reinterpret_cast<int *> (params[8]), reinterpret_cast<int *> (params[9]), reinterpret_cast<int *> (params[10]), params[11],
params[12], params[13], params[14], params[15]);

return ac_pickupid;
}

Вопрос в том, как правильно преобразовать из cell в int*, ибо reinterpret_cast<int *> (params[7]) не помогает и данный код вызывает краш.

Собственно прилагаю еще само объявление нативки из инклуда стримера.
native STREAMER_TAG_PICKUP:CreateDynamicPickupEx(modelid, type, Float:x, Float:y, Float:z, Float:streamdistance = STREAMER_PICKUP_SD, const worlds[] = { -1 }, const interiors[] = { -1 }, const players[] = { -1 }, const STREAMER_TAG_AREA:areas[] = { STREAMER_TAG_AREA:-1 }, priority = 0, maxworlds = sizeof worlds, maxinteriors = sizeof interiors, maxplayers = sizeof players, maxareas = sizeof areas);

Daniel_Cortez
01.01.2019, 22:19
Вопрос в том, как правильно преобразовать из cell в int*, ибо reinterpret_cast<int *> (params[7]) не помогает и данный код вызывает краш.
Ну а что ещё вы ожидали, конвертируя число в указатель?

Суть в том, что передаваемые в params[] адреса массивов - это не физические адреса, а виртуальные (т.е. смещения относительно начала блока памяти скрипта, включающего в себя секции данных и стека/кучи). Чтобы сконвертировать их в адреса физические, предусмотрена функция amx_GetAddr().

// Допустим, у нас адрес массива в params[4]; сконвертируем его в физический адрес
// и запишем в переменную addr.
cell *addr;
if (amx_GetAddr(amx, params[4], &addr) != AMX_ERR_NONE)
{
// Если amx_GetAddr() вернула результат, отличный от AMX_ERR_NONE, это может означать
// только одно: в нативку каким-то образом передан неправильный адрес массива
// (обычно подобные ошибки пресекаются ещё при компиляции скрипта - возможно,
// скриптер пытался вызвать функцию через #emit и неправильно передал указатель?)
// Можно начинать паниковать.
return amx_RaiseError(amx, AMX_ERR_NATIVE), 0;
}
// Конверсия прошла успешно, теперь можно выполнять действия с указателем в addr.
*addr = 0;

Batya_Montes
02.01.2019, 08:05
Ну а что ещё вы ожидали, конвертируя число в указатель?

Суть в том, что передаваемые в params[] адреса массивов - это не физические адреса, а виртуальные (т.е. смещения относительно начала блока памяти скрипта, включающего в себя секции данных и стека/кучи). Чтобы сконвертировать их в адреса физические, предусмотрена функция amx_GetAddr().

// Допустим, у нас адрес массива в params[4]; сконвертируем его в физический адрес
// и запишем в переменную addr.
cell *addr;
if (amx_GetAddr(amx, params[4], &addr) != AMX_ERR_NONE)
{
// Если amx_GetAddr() вернула результат, отличный от AMX_ERR_NONE, это может означать
// только одно: в нативку каким-то образом передан неправильный адрес массива
// (обычно подобные ошибки пресекаются ещё при компиляции скрипта - возможно,
// скриптер пытался вызвать функцию через #emit и неправильно передал указатель?)
// Можно начинать паниковать.
return amx_RaiseError(amx, AMX_ERR_NATIVE), 0;
}
// Конверсия прошла успешно, теперь можно выполнять действия с указателем в addr.
*addr = 0;


Попробовал данный метод и в принципе получилось, но из данного массива достается только либо первый, либо последний элемент.
http://i.prntscr.com/lbHnJUGkTP_TOnPiqFOfTw.png
Пробовал прогнать циклом, но безрезультатно. Как же все таки правильно будет получить весь массив?

- - - Добавлено - - -

UPD: Проблема была в цикле, все прекрасно достается ;)
Можно закрывать.