PDA

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



SpecFree
22.02.2017, 23:59
Добрый вечер, профи, и не только)
Меня интересует такой вопрос: возможно ли вызвать нативную функцию a_samp из плагина не прибегая к помощи Invoke?

ziggi
23.02.2017, 01:23
sampgdk или вызывать функцию по адресу.

vovandolg
23.02.2017, 06:18
Я бы советовал сделать встроенную функцию написанную внутри инклуда твоего,
чтобы стандартные функции вызывались только на сервере,
а потом уже какая инфа от них нужна передавать в плагин.

SpecFree
23.02.2017, 10:48
sampgdk или вызывать функцию по адресу.

По адресу через amx_FindNative? А так будет работать?


Я бы советовал сделать встроенную функцию написанную внутри инклуда твоего,
чтобы стандартные функции вызывались только на сервере,
а потом уже какая инфа от них нужна передавать в плагин.

Так немного не получится, потому что нужно при вызове отправлять одни данные, которые находятся в инклуде, и сверять их с данными, которые только в плагине.
Да и в Invoke я что-то не нашёл нужного натива

Daniel_Cortez
23.02.2017, 13:00
Если вам нужно вызвать нативную функцию без использования сторонних библиотек (gInvoke или SAMPGDK), можете попробовать вызвать её через функцию-посредника на Pawn (т.е. с помощью amx_Exec() вызвать в скрипте public-функцию, которая уже вызовет нужный вам натив) или же в таблице нативных функций скрипта найти нужный натив и вызвать напрямую по адресу (но тогда обязательно нужно, чтобы нативная функция использовалась где-нибудь в скрипте, чтобы она была в таблице нативок; для этого можно просто создать в скрипте пустую public-функцию, которая нигде не используется и вызывает нативную функцию с любыми аргументами).
Второй способ сложнее в реализации, но лучше в плане производительности. Сложность заключается в том, что при вызове AMXLoad ещё нельзя узнать адрес натива, т.к. скрипт загружен, но ещё не инициализирован. Единственный способ - создать в плагине ещё одну нативную функцию, которая будет вызываться скриптом из OnGameModeInit/OnFilterScriptInit (сделать перехват в инклуде), и при вызове этой вспомагательной функции уже из неё узнавать адрес нужной вам нативки.

SpecFree
23.02.2017, 13:32
Но плагин вызывает поиск адреса натива при определённом действии, когда всё уже загружено и, по идее, инициализировано..

И такой вопрос: макрос (к примеру, MAX_PLAYERS) можно перенести в плагин?

Daniel_Cortez
23.02.2017, 14:09
Адрес натива узнать всё тем же amx_FindNative?
Воспользуйтесь этой (https://github.com/maddinat0r/samp-plugin-sdk) модифицированной версией SDK, в ней добавлено несколько доп. функций и макросов (см. файл amx2.h). В частности, вам понадобится макрос GETENTRY.
Код должен получиться примерно такой:


int func_index;
if (amx_FindNative(amx, "<имя натива>", &func_index) != AMX_ERR_NONE)
{
// Ошибка: нативная функция не найдена.
}
AMX_HEADER *hdr = (AMX_HEADER *)amx->base;
AMX_FUNCSTUB *func_stub = GETENTRY(hdr, natives, func_index);
AMX_NATIVE func = func_stub->func;




И ещё такой вопрос: макрос (к примеру, MAX_PLAYERS) можно перенести в плагин?
Почему бы и нет? Просто передавайте эту константу из скрипта в качестве параметра нативной функции в вашем плагине. Или можете вызвать GetPlayerPoolSize непосредственно из плагина.

SpecFree
23.02.2017, 14:10
Слегка отредачил пост выше (UPD)

Daniel_Cortez
23.02.2017, 14:12
Слегка отредачил пост выше (UPD)
Да, уже заметил, но сути это не меняет. Думаю, вам всё равно пригодится ответ на 1-й вопрос.

SpecFree
23.02.2017, 14:32
Но вот касаемо второго: мне нужно создать глобальный массив в самом плагине, думаю, это не подойдёт в качестве параметра функции)

Daniel_Cortez
23.02.2017, 15:14
Но вот касаемо второго: мне нужно создать глобальный массив в самом плагине, думаю, это не подойдёт в качестве параметра функции)
Может уже хватит вокруг да около? Опишите нормально, что вам нужно сделать с помощью плагина. Вполне возможно, что есть более рациональное решение, чем вы предполагаете.

SpecFree
23.02.2017, 15:24
Я же говорю: мне нужно объявить глобальный массив int Array[MAX_PLAYERS];
что бы он хранил в себе число для каждого игрока, и по нему сверять данные сугубо в плагине
А из плагина вызывать функцию IsPlayerInRangeOfPoint. Но это я уже решил вызовом функции-посредника)

Daniel_Cortez
23.02.2017, 15:26
Я же говорю: мне нужно объявить глобальный массив int Array[MAX_PLAYERS];
что бы он хранил в себе число для каждого игрока, и по нему сверять данные сугубо в плагине
А из плагина вызывать функцию IsPlayerInRangeOfPoint. Но это я уже решил вызовом функции-посредника)
Ну так передавайте MAX_PLAYERS из скрипта в плагин, а дальше оператор new вам в помощь (или malloc, если предпочитаете писать код в стиле "Си с классами").

SpecFree
23.02.2017, 15:35
Ну да, как-то не подумал о динамике..
Спасибо за совет :smile:

SpecFree
23.02.2017, 20:42
Даниель, а Вы могли бы мне помочь в ЛС, или скайп, потому что у самого у меня справиться не получается, а здесь невероятно долго?..
Возникла одна проблема, похоже, из-за движка SAMP, либо я что-то неправильно понимаю, такое даже объяснить будет сложно

Daniel_Cortez
24.02.2017, 14:47
Даниель, а Вы могли бы мне помочь в ЛС, или скайп, потому что у самого у меня справиться не получается, а здесь невероятно долго?..
Возникла одна проблема, похоже, из-за движка SAMP, либо я что-то неправильно понимаю, такое даже объяснить будет сложно
Знаю, что немного запоздал с ответом, но нет, индивидуальной помощью я не занимаюсь - тем более, что сейчас почти всё свободное время уходит на кодинг.

SpecFree
24.02.2017, 15:00
Знаю, что немного запоздал с ответом, но нет, индивидуальной помощью я не занимаюсь - тем более, что сейчас почти всё свободное время уходит на кодинг.

К сожалению, моих знаний недостаточно, что бы разобраться в таком вопросе, но Ваших, я почти уверен, вполне хватит, что бы объяснить мне за пять минут что к чему) Что почти не займёт ни Вашего, ни моего времени
Как известно, на русском языке нет никаких подробных туториалов к плагинописанию, а по иностранным разбираться довольно тяжко, поэтому единственным верным решением было бы обратиться именно к Вам.. Если и Вы бы не помогли, то мне оставалось бы идти только на samp.com
Поэтому, моя последняя надежда перед этим - только пообщаться с Вами)
Ведь моё свободное время тоже почти всё, как у Вас, уходит на кодинг..

$continue$
24.02.2017, 15:18
А в чем проблема собственно?

Создаем функцию какую нить getPlayerMax(int max_player). В OnGameModeInit вызываем ее из плагина: getPlayerMax(MAX_PLAYERS). И записываем это значение в какую нибудь переменную.

К сожалению, моих знаний недостаточно, что бы разобраться в таком вопросе, но Ваших, я почти уверен, вполне хватит, что бы объяснить мне за пять минут что к чему) Что почти не займёт ни Вашего, ни моего времени
Как известно, на русском языке нет никаких подробных туториалов к плагинописанию, а по иностранным разбираться довольно тяжко, поэтому единственным верным решением было бы обратиться именно к Вам.. Если и Вы бы не помогли, то мне оставалось бы идти только на samp.com
Поэтому, моя последняя надежда перед этим - только пообщаться с Вами)
Ведь моё свободное время тоже почти всё, как у Вас, уходит на кодинг..

SpecFree
24.02.2017, 15:26
А в чем проблема собственно?

Создаем функцию какую нить getPlayerMax(int max_player). В OnGameModeInit вызываем ее из плагина: getPlayerMax(MAX_PLAYERS). И записываем это значение в какую нибудь переменную.

Проблема давным давно не в этом, а это давно решено. Сомневаюсь, что Вы мне можете помочь

$continue$
24.02.2017, 15:28
Ты перепутал. malloc - Си, а new -Си с классами или я не так понял мысль.

Ну так передавайте MAX_PLAYERS из скрипта в плагин, а дальше оператор new вам в помощь (или malloc, если предпочитаете писать код в стиле "Си с классами").


Значит дальше жди, когда DC поможет тебе в не форума :)

Проблема давным давно не в этом, а это давно решено. Сомневаюсь, что Вы мне можете помочь

SpecFree
24.02.2017, 15:33
Если так хотите, без проблем. Расскажите, какое значение возвращает amx_Exec в retval?

$continue$
24.02.2017, 15:41
Я не писал плагины под SA-MP, но самый полезный навык программиста - уметь пользоваться поисковыми системами.
https://upload.teknik.io/S5Ltf.png

C моим уровнем английского: "Возвращает значение вызываемой функции или NULL, если функция не нуждается в возвращаемом значении".


Если так хотите, без проблем. Расскажите, какое значение возвращает amx_Exec в retval?

SpecFree
24.02.2017, 15:43
Так вот дело в том, что это я давно знаю, НО
Как Вы объясните постоянный возврат единицы при любом исходе кода, но натив сам по себе не выполняет своё прямое действие?

$continue$
24.02.2017, 15:47
А код показать? Без кода трудно, что либо сказать. Залей на gist/pastbin

Так вот дело в том, что это я давно знаю, НО
Как Вы объясните постоянный возврат единицы при любом исходе кода, но натив сам по себе не выполняет своё прямое действие?

P.S: вк - https://vk.com/id123663731, telegram: @continue98

SpecFree
24.02.2017, 15:55
Вот (https://yadi.sk/i/HqtapK8c3EWKCD) код конкретной функции, которая работает неправильно.
Думаю, здесь есть какие-то особенности для выполнения

$continue$
24.02.2017, 16:07
Ну так правильно, не?


main()
{
new pickup_armour = CreatePickup ( 1242, 2, 1503.3359, 1432.3585, 10.1191 );
new ret = DestroyPickup(pickup_armour);
printf("%d", ret);
}


Вот (https://yadi.sk/i/HqtapK8c3EWKCD) код конкретной функции, которая работает неправильно.
Думаю, здесь есть какие-то особенности для выполнения
https://upload.teknik.io/A2BYn.png

SpecFree
24.02.2017, 16:14
Так дестрой вызывается по адресу из плагина. Смысл от этого кода?
Пикап не удаляется, а в плагин возвращается 1. В моде-то всё работает нормально

$continue$
24.02.2017, 16:15
Уже другой вопрос. Ты спросил почему постоянно возвращается 1 - я ответил. Теперь уже почему не удаляет.

Так дестрой вызывается по адресу из плагина. Смысл от этого кода?
Пикап не удаляется, а в плагин возвращается 1. В моде-то всё работает нормально

SpecFree
24.02.2017, 16:23
Да это всё было примерно одним вопросом, но к Даниелю.. Он должен разбираться в таких делах, а я даже не знаю что искать...
Просто это даже не первая функция, которая возвращает 1, а сама не выполняется

SpecFree
24.02.2017, 18:26
Кстати, DestroyPickup возвращает 1 в случае успеха, и 0 в обратном.




public OnGameModeInit()
{
pick1 = CreatePickup(1212, 23, 2.0, 3.0, 4.0);
pick2 = CreatePickup(1212, 23, 1963.4354, 1357.6333, 9.2578);
pick3 = CreatePickup(1212, 23, 5.0, 6.0, 7.0);
pick4 = CreatePickup(1212, 23, 8.0, 9.0, 10.0);
pick5 = CreatePickup(1212, 23, 11.0, 12.0, 13.0);
pick6 = CreatePickup(1212, 23, 14.0, 15.0, 16.0);

printf("Пикап номер %i (%i)", pick1, IsValidPickup(pick1));
printf("Пикап номер %i (%i)", pick2, IsValidPickup(pick2));
printf("Пикап номер %i (%i)", pick3, IsValidPickup(pick3));
printf("Пикап номер %i (%i)", pick4, IsValidPickup(pick4));
printf("Пикап номер %i (%i)", pick5, IsValidPickup(pick5));
printf("Пикап номер %i (%i)", pick6, IsValidPickup(pick6));

printf("Пикап номер pick3 удаляется (%i)", DestroyPickup(pick3));
printf("Пикап номер 12 удаляется (%i)", DestroyPickup(12));

return 1;
}



[15:12:51] Пикап номер 0 (1)
[15:12:51] Пикап номер 1 (1)
[15:12:51] Пикап номер 2 (1)
[15:12:51] Пикап номер 3 (1)
[15:12:51] Пикап номер 4 (1)
[15:12:51] Пикап номер 5 (1)
[15:12:51] Пикап номер pick3 удаляется (1)
[15:12:51] Пикап номер 12 удаляется (0)

Duck_Leo
24.04.2021, 15:33
Привет. Например я хотел бы использовать самповскую родную функцию GetPlayerMoney в плагине. Не хотелось бы использовать GDK и др.
Как это пытаюсь сделать:
// C++

int __GetPlayerMoney(int playerid, AMX *amx)
{
int amx_index;
cell amx_retval = 0;

if (!amx_FindNative(amx, "GetPlayerMoney", &amx_index))
{
amx_Push(amx, playerid);
amx_Exec(amx, &amx_retval, amx_index);
}
return (int)amx_retval;
}

// native PLUGIN_GetPlayerMoney(playerid);
static cell AMX_NATIVE_CALL n_PLUGIN_GetPlayerMoney(AMX *amx, cell *params)
{
return __GetPlayerMoney(params[1], amx);
}

AMX_NATIVE_INFO NATIVES_LIST[] =
{
{"PLUGIN_GetPlayerMoney", n_PLUGIN_GetPlayerMoney},
{ 0, 0 }
};

// Pawn

native PLUGIN_GetPlayerMoney(playerid);

public OnPlayerSpawn(playerid)
{
new money = PLUGIN_GetPlayerMoney(playerid);
printf("money = %d", money);
return 1;
}

forward CallGetPlayerMoney();
public CallGetPlayerMoney()
{
GetPlayerMoney(0);
}
В итоге в printf'е money = 1. А по задумке ф-ия должна вернуть текущие деньги игрока.
Что я делаю не так?