Доступ к функциям C ++ из текстового хранилища - PullRequest
1 голос
/ 29 марта 2010

Мне интересно, знает ли кто-нибудь, как сделать следующее:

Допустим, у меня есть куча данных, хранящихся в SQL, скажем, одно из полей может называться funcName, имя функции будет содержать данные, аналогичные "myFunction". Мне интересно, есть ли способ, чем в свою очередь извлечь имя функции и фактически вызвать эту функцию?

Есть несколько способов, которыми я могу придумать для достижения этой цели, один из которых - изменить funcName на funcId и связать его с массивом или подобным, но я ищу что-то более динамичное, что позволило бы мне добавить данные летать без необходимости обновления фактического исходного кода каждый раз, когда я добавляю вызов к новой функции, при условии, конечно, что функция уже существует и доступна через область видимости, из которой мы ее вызываем.

Любая помощь будет принята с благодарностью.

Ответы [ 4 ]

3 голосов
/ 29 марта 2010

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

// callable_function.h
class CallableFunction {
 public:
  virtual void operator()() = 0;
};

class CallableFunctionRegistry {
 public:
  static CallableFunction *Register(const string &func_name,
                                    CallableFunction *func_impl) {
    Instance()->registered_functions_.insert(make_pair(func_name, func_impl));
  }

  static void Run(const string &func_name) {
    (*Instance()->registered_functions_[func_name])();
  }

 private:
  static CallableFunctionRegistry *Instance() {
    static CallableFunctionRegistry *instance = new CallablefunctionRegistry;
    return instance;
  }

  CallableFunctionRegistry() {}
  map<string, CallableFunction*> registered_functions_;
};

#define REGISTER_CALLABLE_FUNCTION(FuncName) \
  class FuncName : public CallableFunction { \
   public: \
    virtual void operator()(); \
  }; \
  CallableFunction *impl_ ##FuncName = \
    CallableFunctionRegistry::Register(#FuncName, new FuncName); \
  void FuncName::operator()()

И используйте это так:

//other_file.cc
REGISTER_CALLABLE_FUNCTION(DoStuff) {
  // do stuff here.
}

А это:

//yet_another_file.cc
CallableFunctionRegistry::Run("DoStuff");

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

2 голосов
/ 29 марта 2010

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

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

1 голос
/ 29 марта 2010

Подход № 1 (самый сложный):
Разработайте систему плагинов, состоящую из нескольких динамически связанных библиотек (* .dll в win, * .so в linux), с несколькими общедоступными функциями, которые сообщат вашему приложению о том, что этот плагин поддерживает, имена функций и указатели. Сканирование плагинов при запуске, создание списка функций, которые будут сопоставлять имена функций с их указателями.

Ожидаются проблемы с переменным количеством параметров.

Подход № 2 (перебор): Храните все функции, которые вы должны вызывать, в одной динамически связанной библиотеке. Когда имя функции извлекается из базы данных, получите указатель на функцию, используя GetProcAddress (win32) или dlsym (?) В Linux.

Ожидаются проблемы с переменным количеством параметров. Не самый быстрый и не самый умный способ.

Подход № 3 (наиболее гибкий): Добавьте переводчик lua ​​или python в ваше приложение.
Таким образом, вы сможете хранить целые функции в базе данных, и у вас не должно возникнуть проблем с вызовом одной из них. Вам все равно придется объявить список функций, к которым вы хотите получить доступ.

Это не будет доказательством дурака / взлома, однако можно будет испортить все приложение из базы данных, если вы не будете достаточно осторожны.

1 голос
/ 29 марта 2010

Вы можете использовать текст, полученный из SQL, и вызвать GetProcAddress ()

это даст вам указатель на функцию, которую вы можете вызвать (при условии, что вы используете Windows).

Для Linux взгляните на dlsym

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...