Переменные вызовы функций в D

ОК, вот что мне нужно:

  • Допустим, у нас есть строковая переменная, например, func с некоторым значением, заданным пользователем (не постоянная)
  • Как мы можем вызвать функцию, имя которой является значением func?

ОБНОВИТЬ:

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

string func = "myfunc";

Мне нужно что-то вроде call(func), который позвонит myfunc, Как и в PHP call_user_func_array ()


Есть идеи?

Я посмотрел на Примеси но это не похоже на то, что мне нужно.


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

5

Решение

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

Как предложил user3286380, один из способов решения этой проблемы, который будет работать на всех языках, — это создать таблицу, в которой перекрестные ссылки на имена функций и указатели на соответствующие функции. Затем ваша программа может просматривать эту таблицу во время выполнения.

Если рассматриваемый язык допускает самоанализ (во время выполнения или во время компиляции), вы можете перечислить функции в вашем модуле или программе и найти функцию, имя которой ввел пользователь. В D вы можете сделать это, используя allMembers черта характера на модуле. Это даст вам массив всех объявлений в модуле; Следующим шагом будет фильтрация функций, проверка соответствия сигнатуры функции, а затем создание оператора switch, который вызывает соответствующую функцию. Вы можете использовать CTFE и струнные миксины для достижения вышесказанного.

4

Другие решения

Создайте массив пар, где первый элемент каждой пары будет именем строковой функции, а второй — указателем на функцию. Поиск в массиве и, когда имя найдено, вызвать его с помощью указателя. Обратите внимание, что в Python есть класс словаря, который позволяет вам делать это как пары ключ: значение.

1

Я вижу 3 способа сделать это:

  • Если вы заранее знаете набор функций, из которых можно выбирать, вы можете зарегистрировать ассоциативную таблицу string -> functor где функтор записывает адрес функции и подпись, что-то вроде std::function в C ++

  • В противном случае, более сложным решением является проверка отладочных символов вашего собственного исполняемого файла и построение таблицы из этого. Вы также можете использовать препроцессоры (например, Mt Qt) для построения этой таблицы, или в случае D использовать встроенную рефлексивность во время компиляции.

  • Если вам действительно нужна гибкость, используйте интерпретатор вместо компилятора. Цепляться хороший интерпретатор C ++ на основе LLVM с компиляцией точно в срок

1

Единственный способ, которым я когда-либо делал это раньше, — это связать функции в вашем исполняемом файле со строкой, которая «называет» эту функцию, а затем выполнить сравнение.

Я думал, что приведу простой (1 функция) пример для вас на C, я должен предположить, что это работает и на D:

typedef struct {
char * func_name;
void (* fptr)();
} myS;

void print(){
printf("hello world\n");
}

int main()
{
myS Ex;
char str[100] = "";

// Obviously you can fill these in a more intelligent manner, use an array, etc
Ex.func_name = malloc(strlen("print")+1);
strcpy(Ex.func_name, "print");
Ex.fptr = print;

printf("Enter the function name\n");
scanf("%99s", str);

// and of course with a number of functions to examine you could use a switch
if(!strcmp(str, Ex.func_name))
Ex.fptr();
else
printf("Didn't find a function to call\n");

return 0;
}
1

Я использую ассоциативные массивы. Примером может быть:

module main;

import std.stdio;

class Tqfuncs{
private:
void qwrite(string arg){
write(arg);
}
void delegate(string)[string] pList;//store name & pointer to functions here
public:
this(){
pList = [
"qwrite":&qwrite,//add the qwrite function
];
}
void call(string name, string arg){
if (name in pList){
pList[name](arg);//call the function
}else{
throw new Exception("unrecognized function call "~name);
}
}
}

void main(string[] args){
Tqfuncs scrF = new Tqfuncs;
scrF.call("qwrite","This will be written");
}

Я создал динамический язык сценариев, используя этот подход, вы можете узнать больше, используя источник https://github.com/Nafees10/qscript .
Тем не менее, есть некоторые ограничения, использующие этот метод:

  • Все функции должны быть в определенном «формате». Как я использовал void functionName(string arg), Но есть обходной путь, если вам интересно, вы можете проверить это в QScript (мой проект).
0

Нет — это не нужно в статически типизированном языке! Период.

Зачем? — потому что компилятор не может знать заранее значение (измененное во время выполнения) переменной, содержащей имя функции, которую вы хотите запустить, когда он встречает funcname(myvar) какой машинный код он должен генерировать там?

Представь на секунду, что ты хочешь работает:

string funcname;
// here some initialisation code that modifies the funcname
int someVal = funcall(funcname);

Что происходит, когда funcall () получает имя функции, которая возвращает, скажем, объект Person (пользовательский тип) ??

Кроме того, что происходит, когда нет функции с именем funcname?? Ошибка во время выполнения? Нет ошибок? Какие?

То, что вы хотите, находится в области динамических языков, где безопасность типов полностью игнорируется (что, к сожалению, большинство из них).

ОДНАКО … Если все ваши функции обернуты в структуру для примера, то D предоставляет элегантный способ делать то, что вы хотите через пересылка (функция рассылки). Об этом подробнее здесь: https://dlang.org/spec/operatoroverloading.html#dispatch

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector