在C ++中动态调用处理函数

时间:2012-01-01 06:07:48

标签: c++ web-applications dispatcher

我正在尝试了解特定的Web架构。 有一个cgi Web应用程序以这种方式工作。

来自Web浏览器的请求来到apache Web服务器,然后将其路由到应用程序调度程序。

应用程序调度程序有一个配置文件,其中包含所有可能的命令及其相应的处理程序方法。

假设,如果浏览器发出cmd=_login请求,调度程序会查找可能包含此条目的配置文件。

  

命令:_login

     

处理程序:handle_login()

     

标题:login.h

     

二进制:Exe_name

那么,应用程序调度程序可以通过什么方式分叉cgi二进制文件(Exe_name)并直接调用handle_login()函数?

可以直接调用特定方法吗?

2 个答案:

答案 0 :(得分:3)

基本上有两种方法可以进行符号解析。

内置符号解析。

根据您的系统,您可以在运行时使用的隐藏符号表中按名称查找常规函数。例如,类UNIX系统上的dlopen()dlsym()允许您加载共享库,并按名称解析该库中的函数。对于动态链接库(DLL),Windows具有类似的行为函数LoadLibrary()GetProcAddress()。您必须注意可见性的概念。函数必须由库导出才能使用此机制进行解析。我相信GCC默认创建导出所有功能(可见性是公共的),Windows编译器默认不导出任何内容。另请注意,在Windows上,您可以在不加载外部库的情况下解析主机程序中的函数,因为空库句柄指定了主机进程的可执行映像。

一般来说,这充满了细微之处,而且不便携。我不建议您基于此机制构建系统。

手动符号解析:路线

将URL(或部分URL)映射到函数的现代方法是构建URL routes 。大多数基于MVC范例(Ruby on Rails,Django和ASP.NET MVC等)的现代Web框架都采用了这种方法,其中还有很多其他方法。

这基本上包括构建一个名称(或正则表达式)到回调的映射(在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);
}

答案 1 :(得分:0)

您不清楚自己是使用Windows还是Linux,但是加载模块并在其中执行给定功能的能力是模块的标准功能。

以下是Win32 API中的两个相关/有用的功能:

LoadLibrary

GetProcAddress