Существует два основных подхода к разрешению символов.
Встроенное разрешение символов.
В зависимости от вашей системы, вы можете искать обычные функции по имени в скрытомтаблица символов используется во время выполнения.Например, dlopen()
и dlsym()
в UNIX-подобных системах позволяют загружать библиотеку общих объектов и разрешать функции в этой библиотеке по имени.Windows имеет аналогичные функции LoadLibrary()
и GetProcAddress()
для динамически связанных библиотек (DLL).Необходимо обратить внимание на понятие видимость .Функции должны быть экспортированы библиотекой для разрешения с помощью этого механизма.Я считаю, что GCC создает экспорт всех функций по умолчанию (видимость общедоступна), а компиляторы Windows по умолчанию ничего не экспортируют.Также обратите внимание, что в Windows вы можете разрешать функции в программе хоста, не загружая внешнюю библиотеку, поскольку дескриптор нулевой библиотеки обозначает исполняемый образ процесса хоста.
В общем, это полно тонкостей и не переносимо.Я не рекомендую вам создавать систему, основанную на этом механизме.
Ручное разрешение символов: маршруты
Современный способ отображения URL-адресов (или частей URL-адресов) на функции заключается в создании URL-адреса маршруты .Этот подход принят большинством современных веб-фреймворков, основанных на парадигме MVC (Ruby on Rails, Django и ASP.NET MVC и многие другие).
Это в основном состоит в построении картыимен (или регулярных выражений) для обратных вызовов (в C ++ это будет указатель на функцию или объект std::function<>
).Если ваш компилятор поддерживает новый стандарт, вы должны иметь возможность заполнить объект std::map< std::regex,std::function<void()>>
для реализации поиска.
Вот простой (не проверенный) пример:
// GET request for login.
void handle_login_page ()
{
// CGI handler: read from `std::cin` and write to `std::cout`...
}
// POST request for login.
void handle_login_form ()
{
// CGI handler: read from `std::cin` and write to `std::cout`...
}
typedef std::function<void()> Handler;
typedef std::map<std::string, Handler> Routes;
void handle_request ( const Routes& routes, const std::string& command )
{
// locate handler.
Routes::const_iterator match = routes.find(command);
if (match == routes.end()) {
// exit with 404 status.
}
const Handler handler = match->second;
// log access or other pre-processing.
// ...
// invoke handler.
handler();
}
int main ()
{
Routes routes;
routes["get_login"] = &handle_login_page;
routes["post_login"] = &handle_login_form;
// ...
// accept a connection.
// fork.
// get command name.
const std::string command = ...;
handle_request(routes, command);
}