Просмотр полной версии : [Вопрос] Можно ли создать public-функции с ограниченной областью (static) видимости?
Как я знаю, можно ограничить область видимости обычных функций с помощью "static". Можно ли как нибудь ограничить область видимости колбеков, чтобы они были доступны только в одном файле?
У меня получилось ограничить таким способом:
static @SomeFunc();
static @SomeFunc() { }
Но это не совсем то, что я хочу. То есть этот метод функционирует не так как обычные функции с ограниченной областью видимости. Конечно в этом случае тоже нельзя вызывать функцию из другого файла, но и нельзя создать функцию с анологичным называнием.
Есть идеи? Можно ли как нибудь это реализовать?
Эмм, ты создаёшь публичные (общедоступные) функции и хочешь ограничить их зону видимости? :crazy: Не находишь противоречия в своих словах?
Эмм, ты создаёшь публичные (общедоступные) функции и хочешь ограничить их зону видимости? :crazy: Не находишь противоречия в своих словах?
Нет, противоречивости не нахожу, ибо у меня есть конкретная цель. Как по твоему устанавливать таймер для обычных функций? Или тот же мускул? Мне нужна функция, которую можно использовать в одном файле (точнее ограничить зону использование), но при этом можно было вызывать через таймер.
Паблик функции на то и паблик, что их область видимости нельзя ограничить не только для одного файла, но даже для одного скрипта.
Паблик функции на то и паблик, что их область видимости нельзя ограничить не только для одного файла, но даже для одного скрипта.
Ну я это понимаю. Но я объяснил, что мне нужно. Обычным функциям нельзя обращаться через название при вызове (компилятор генерирует адрес для них, как я понимаю). А паблик функциям можно обращаться через название (т.к. компилятор делает это возможным) насчёт чего их можно вызывать с помощью таких функций как Call(Local/Remote)Function | SetTimer(Ex) | mysql_(t/p)query | и т. д. и т. п.
Короче говоря, нельзя реализовать то, что я хочу?
- - - Добавлено - - -
Я уточнил, оказывается это не возможно, можно закрывать тему.
Теоретически можно и обычную функцию с помощью таймера вызвать, но нужно ли это? Чтобы уменьшить вероятность совпадения названий функций - делайте их как можно больше.
Daniel_Cortez
22.05.2018, 16:59
Конечно в этом случае тоже нельзя вызывать функцию из другого файла, но и нельзя создать функцию с анологичным называнием.
Только что проверил - оказывается, можно.
myinc.inc
static @SomeFunc();
static @SomeFunc()
{
emit const.pri 0;
}
main.p:
#include "myinc.inc"
@SomeFunc();
@SomeFunc()
{
emit const.pri 1;
}
main()
{
@SomeFunc();
}
Вывод pawndisasm:
00000000 halt 00000000
00000008 proc ; @SomeFunc
0000000c const.pri 00000000
00000014 zero.pri
00000018 retn
0000001c proc ; @SomeFunc
00000020 const.pri 00000001
00000028 zero.pri
0000002c retn
00000030 proc
00000034 push.c 00000000
0000003c call 0000001c ; @SomeFunc
00000044 zero.pri
00000048 retn
Как видно из листинга, создаются две public-функции с одинаковым именем. В таблице экспортируемых (public-) функций название "@SomeFunc" тоже дублируется. Нужно будет сообщить об этом баге...
Также интересно, что CallLocalFunction перед вызовом отыскивает нужную функцию по названию в таблице public-функций, причём использует не линейный, а бинарный поиск. Это означает, что из двух и более функций с одинаковым названием CallLocalFunction может вызвать любую из них. Например, сейчас она может вызывать вторую, а добавь или удали какую-нибудь ещё public-функцию, и вызываться будет первая.
Ну смотри: ты хочешь в разных файлах создавать паблики с одинаковыми именами. Далее представим, что ты решил вызвать один из пабликов при помощи CallRemoteFunction: каким образом сервер поймёт к какому именно ты обращаешься паблику?
Чтоб такое реализовать, нужно, как я понимаю, модифицировать процесс регистрации паблик функций, добавляя отдельную "таблицу" со static пабликами. И уже для обращения к этим пабликам делать отдельные функции, которые уже не смогут обращаться к каким-то пабликам за пределами файла. Ну и решить ещё ряд подводных камней. В итоге, ты получишь обрубок обычных функций и не более того.
Как вариант, можешь попробовать использовать автоматоны. Но в данном случае это будет больше как извращение, чем полезная фича
А можно ли обычную функцию вызвать через адрес? И как узнать адрес функций?
Nexius_Tailer
22.05.2018, 17:14
Так а если сделать что-то вроде обёртки для конкретных функций, в которой будет объявляться паблик с таким же именем и из него будет вызываться эта функция? Вполне как вариант, если таких конкретных функций не очень много (т.к. объявлять каждую из них надо будет через этот дефайн-обёртку). Единственная проблема это область видимости, коя хоть и будет на все файлы и скрипты, но в большинстве случаев это не так критично (особенно если делаешь просто для себя).
особенно если делаешь просто для себя.
Ну и проблема то в том, что не для себя. Если бы для себя, зачем себя ограничивать от вызова функций или название такой же функций (я же буду знать, что можно | что нельзя)
Мне нужно ограничить вызов функций, которая находится в конкретном файле. Но в этом самом файле идет обращение к этой функции через название, что делает не возможным создать её как обычную и ограничить зону через static.
Только что проверил - оказывается, можно.
myinc.inc
static @SomeFunc();
static @SomeFunc()
{
emit const.pri 0;
}
main.p:
#include "myinc.inc"
@SomeFunc();
@SomeFunc()
{
emit const.pri 1;
}
main()
{
@SomeFunc();
}
Вывод pawndisasm:
00000000 halt 00000000
00000008 proc ; @SomeFunc
0000000c const.pri 00000000
00000014 zero.pri
00000018 retn
0000001c proc ; @SomeFunc
00000020 const.pri 00000001
00000028 zero.pri
0000002c retn
00000030 proc
00000034 push.c 00000000
0000003c call 0000001c ; @SomeFunc
00000044 zero.pri
00000048 retn
Как видно из листинга, создаются две public-функции с одинаковым именем. В таблице экспортируемых (public-) функций название "@SomeFunc" тоже дублируется. Нужно будет сообщить об этом баге...
Также интересно, что CallLocalFunction перед вызовом отыскивает нужную функцию по названию в таблице public-функций, причём использует не линейный, а бинарный поиск. Это означает, что из двух и более функций с одинаковым названием CallLocalFunction может вызвать любую из них. Например, сейчас она может вызывать вторую, а добавь или удали какую-нибудь ещё public-функцию, и вызываться будет первая.
Хм, странно, что не работает проверка на совпадение одинаковых названий.
Y_Less утверждает, что вызывается та функция которая находится в области видимости:
Сообщение от Y_Less:
That seems pretty clear and correct to me. It calls the one visible in the current scope (0000001c in the assembly).
https://i.imgur.com/Y73OxRP.jpg
Мне нужно ограничить вызов функций, которая находится в конкретном файле. Но в этом самом файле идет обращение к этой функции через название, что делает не возможным создать её как обычную и ограничить зону через static.
В смысле? Если тебе не нужно вызывать функцию через таймер, то и публичной её делать не обязательно, раз тебе нужно вызывать её только внутри файла.
Опиши подробнее что именно ты хочешь сделать.
Если тебе не нужно вызывать функцию через таймер, то и публичной её делать не обязательно, раз тебе нужно вызывать её только внутри файла.
Эммм, я вроде сказал, что нужно вызывать через таймер, только внутри файла. В первом посту (вроде)
Эммм, я вроде сказал, что нужно вызывать через таймер, только внутри файла. В первом посту (вроде)
А в чём проблема сделать уникальное имя? :scratch_one-s_head: По-моему, ты опять пытаешься создать проблему на ровном месте :)
Это ведь, как уже выяснилось, ни только не реализуемо, так ещё и понимание кода поломает, ибо даже если бы была возможность создать функцию таймера с ограниченной зоной видимости, этим никто в SA-MP не пользовался до тебя, поэтому люди, при виде одинаковых функций и куче одинаковых таймеров, будут не понимать что происходит в твоём коде.
А в чём проблема сделать уникальное имя? :scratch_one-s_head: По-моему, ты опять пытаешься создать проблему на ровном месте :)
ибо даже если бы была возможность создать функцию таймера с ограниченной зоной видимости, этим никто в SA-MP не пользовался до тебя.
Мне просто инетересно. Есть много путей выхода из данной ситауции, но я хочу попробовать именно такую (если возможно).
Велосипедом тоже не пользовались пока его не придумали.
Daniel_Cortez
22.05.2018, 19:41
А можно ли обычную функцию вызвать через адрес? И как узнать адрес функций?
emit const.pri SomeFunc;
emit push.c 0;
emit call.pri;
emit stack ((cellbits / charbits) * 1);
Как-то так. Доступно в последних версиях компилятора.
Y_Less утверждает, что вызывается та функция которая находится в области видимости:
Ну вот кто просил? Наверняка вопрос поставил неверно и тебя не так поняли.
Дай хоть ссылку, что ли, попробую объяснить там, в чём именно проблема (хоть теперь это и может оказаться сложнее).
emit const.pri SomeFunc;
emit push.c 0;
emit call.pri;
emit stack ((cellbits / charbits) * 1);
Как-то так. Доступно в последних версиях компилятора.
Кстати, данный код можно ещё использовать в макросах.
Видимо, проблема была решена http://forum.sa-mp.com/showthread.php?t=654148
emit const.pri SomeFunc;
emit push.c 0;
emit call.pri;
emit stack ((cellbits / charbits) * 1);
Как-то так. Доступно в последних версиях компилятора.
Ну вот кто просил? Наверняка вопрос поставил неверно и тебя не так поняли.
Дай хоть ссылку, что ли, попробую объяснить там, в чём именно проблема (хоть теперь это и может оказаться сложнее).
http://forum.sa-mp.com/showthread.php?p=4022174#post4022174
Он был прав, вызывается тот который находится в зоне видимости
Daniel_Cortez
23.05.2018, 16:53
Сообщил (https://github.com/pawn-lang/compiler/issues/306) о баге на GitHub.
Предлагаемые способы исправления:
Если функция объявлена со спецификатором static и её название начинается с "@", проверить, если функции с таким же названием в других областях видимости, если есть - выдать ошибку.
Запретить объявлять функции со спецификатором static, если имя функции начинается с "@" (компилятор уже считает неправильной комбинацию из "public" и "static").
ИМХО, второй вариант наиболее логичный, но всё же есть смысл быть готовым к любому исходу.
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot