typedef (TResult __fastcall *pMyFunc) (const TParams &Params); // Объявляем указатель на функцию
const AnsiString cseInvalid_Name = "Неизвестное имя функции (%s).";
const AnsiString cFunc_Names [] = {"Func1", "Func2"}; // Имена функций
const pMyFunc cFunc_Ptrs [] = {Func1, Func2}; // Адреса функций
const int cFunc_Count; // Кол-во функций
TRes __fastcall Call_Functions (const AnsiString Name, const TParams &Params)
{[INDENT]for (int i = cFunc_Count-1; i >= 0; i--) // цикл обработки списка функций[INDENT]if (Name.AnsiCompareIC (cFunc_Names ) == 0) // Сравнение имён функций[INDENT]return cFunc_Ptrs (Params); // Вызов функции и возвращение результата
[/INDENT][/INDENT]throw Exception (Format (cseInvalid_Name, &TVarRec (Name), 0)); // Сообщение об ошибке
[/INDENT]}
Помогите с названиями функций
т.е. если строка = deletewindows, то мне надо вызвать функцию deletewindows.
сами функции уже определены и все параметры я сам укажу. меня интересует вопрос как вызвать функцию, если её имя у меня есть в переменной строке?
Код:
Код:
AnsiString f = "KGS"; // то, что меняется
f = "Format_"+f; // полное имя функции
(функция с именем f) (param); //вызов самой функции
f = "Format_"+f; // полное имя функции
(функция с именем f) (param); //вызов самой функции
Вот только как сказать Билдеру, что в последней строке f - это имя функции?
Билдер - компилятор, а не интерпретатор, поэтому как-нибудь так НИКАК.
Код:
const AnsiString Func_Names[] = {"Func1, Func2, .... , FunkK};
//....
TRes Func_Selector (const AnsiString Name, int Param1, double Param2, ... TParam ParamN)
{[INDENT]
return (Name.AnsiCompareIC (Func_Names [0]) == 0) ? // Условие 1
Func1 (Param1, Param2); // Вызов функции 1
: (Name.AnsiCompareIC (Func_Names [1]) == 0) ? // Условие 2
Func1 (Param2, Param1); // Вызов функции 2
: (Name.AnsiCompareIC (Func_Names [K]) == 0) ?
FuncK (ParamN) ; // Вызов функции K
: TRes() ; // Результат "по умолчанию" для неизвестного имени функции
}[/INDENT]
//....
TRes Func_Selector (const AnsiString Name, int Param1, double Param2, ... TParam ParamN)
{[INDENT]
return (Name.AnsiCompareIC (Func_Names [0]) == 0) ? // Условие 1
Func1 (Param1, Param2); // Вызов функции 1
: (Name.AnsiCompareIC (Func_Names [1]) == 0) ? // Условие 2
Func1 (Param2, Param1); // Вызов функции 2
: (Name.AnsiCompareIC (Func_Names [K]) == 0) ?
FuncK (ParamN) ; // Вызов функции K
: TRes() ; // Результат "по умолчанию" для неизвестного имени функции
}[/INDENT]
Пример "притянут за уши", так что за огрехи реализации и более чем сомнительную целесообразность прошу не ругать :)
В общем, моё первое решение вполне пригодно для вызова однотипных функций, а ради разнотипных "огород городить" просто не стоит - проще
Как вариант, можно вызывать функции без параметров, которые будут сами считывать значения из полей формы и использовать их для вызыва функций с параметрами.
А можно ли с помощью, каких-то приведений (не путать с привидениями ;-) указать Билдеру, что вызвать нужно (функцию с именем f)?
Поясните, что к чему приводить требуется приводить?
AnsiString F = "DeleteWindows"-> DeleteWindows();
Причём значения строки меняются, соответственно меняются названия вызываемых функций. Параметры у всех функций одинаковы. Но это не важно. Просто перебором через массив или обычным IF уже работает, но это долговато.
Может есть такое (Function)(F)() или подоббное чё-нить?
Профессионалы меня поймут однозначно!
AnsiString F = "DeleteWindows"-> DeleteWindows();
Причём значения строки меняются, соответственно меняются названия вызываемых функций. Параметры у всех функций одинаковы. Но это не важно. Просто перебором через массив или обычным IF уже работает, но это долговато.
Может есть такое (Function)(F)() или подоббное чё-нить?
Профессионалы меня поймут однозначно![/QUOTE]
Ну вроде сказали уже, что не получится так. Тем более, что, как я понимаю, функции твои-же. Суть в том, что в скомпилированом бинарнике названия функций не хранятся(не считаю экспорт и импорт) - там только адреса, а вычислить значение AnsiString (в общем случае) на этапе компиляции билдер не сможет.
Так вот у меня и есть планы вывести функции в ДЛЛ и соответственно поименно из самой проги их оттудова и звать. С вызовом и ДЛЛки я разобрался, а сабж остался открытым.
Если предполагается, что строка не константная, то такой специальной функции, чтобы вызывала другую функцию, зная её имя, не существует. Её можно написать самому, зная, в какой библиотеке хранится вызываемая функция и используя справочную литературу по формату PE. Граничит с хакерством.
Это меня должно отпугнуть? Для меня хакер - это программист, который хочет разобраться во всех тонкостях. А вот в каких целях он использует свои знания - это определяет УК.
У меня пока цели благотворные.
Не согласен. Хакер так или иначе имеет дело с машинным кодом и должен хоть немного в нём разбираться. Можно быть хорошим программистом и разбираться во всех тонкостях своего языка, но не иметь ни малейшего представления о том, как это всё работает на самом деле. Уметь копаться в исполняемых файлах прикладному программисту вовсе не обязательно. Но можно, если очень хочется. С другой стороны, хакер может не быть программистом.
FARPROC GetProcAddress(HMODULE hModule, LPCSTR lpProcName);
Спасибочки большое!
А я её пролистал, блин, мельком думал перенесу в ДЛЛ и разберуся - забыл!
Спасибо!
А говорили нельзя, нельзя.
Ну 100% и в самой проге такое мона сделать, тока никто видимо не задавался серьёзно этим вопросом.
Цитата:
GetProcAddress
Чтоб я сдох! :D
В смысле? Не надо так всё близко к сердцу принимать ;-)
А говорили нельзя, нельзя.
Ну 100% и в самой проге такое мона сделать, тока никто видимо не задавался серьёзно этим вопросом.[/QUOTE]
Только учти, что эти функции дебе придется экспортировать со всеми вытекающими сложностями.
В принципе не обязательно экспортировать из DLL, можно экспортировать (и тут же импортировать с помощью GetProcAddress) прямо из EXE.
P.S. IMHO не очень красивое решение.
Спасибо ещё раз всем.
Для меня занятие на ближайшую неделю есть...