slighttpd基于lighttpd架构的Server项目实战(10)—插件&动态库

Posted jiange_zh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了slighttpd基于lighttpd架构的Server项目实战(10)—插件&动态库相关的知识,希望对你有一定的参考价值。

上一节我们介绍了状态机,本节我们将添加插件模块,之后就可以根据公共接口来开发插件,而我们的server则只需要通过状态机调用相应阶段的公共函数,无需关心插件的实现细节。我们的插件将以动态库so的形式来加载。

插件

我们的插件类将作为一个基类,成员函数作为虚函数,之后由插件开发者继承、实现。

本项目的插件接口对应于状态机的阶段,每个阶段提供一个函数:

/*************************************************************************
    > File Name: plugin.h
    > Author: Jiange
    > Mail: [email protected] 
    > Created Time: 2016年02月10日 星期三 18时46分22秒
 ************************************************************************/

#ifndef _PLUGIN_H
#define _PLUGIN_H

class Worker;
class Connection;

typedef enum
{
    PLUGIN_READY,
    PLUGIN_NOT_READY,
    PLUGIN_ERROR
} plugin_state_t;

class Plugin
{
    public:
        Plugin();
        virtual ~Plugin();

        virtual bool Init(Connection *con, int index);
        virtual bool RequestStart(Connection *con, int index);
        virtual bool Read(Connection *con, int index);
        virtual bool RequestEnd(Connection *con, int index);
        virtual bool ResponseStart(Connection *con, int index);
        virtual plugin_state_t Write(Connection *con, int index);
        virtual bool ResponseEnd(Connection *con, int index);
        virtual void Close(Connection *con, int index);

        virtual bool Trigger(Worker* worker, int index);
        virtual bool LoadPlugin(Worker* worker, int index);
        virtual void FreePlugin(Worker* worker, int index);

        typedef Plugin* (*SetupPlugin)();
        typedef void    (*RemovePlugin)(Plugin *plugin);

        SetupPlugin setup_plugin;
        RemovePlugin remove_plugin;

        void* plugin_data;
        void* plugin_so;
        int   plugin_index;
        bool  plugin_is_loaded;
};

#endif

动态库加载

const char *path = so_path; //动态库so的路径

/* dlopen()函数以指定模式打开指定的动态链接库文件,
 * 并返回一个句柄给dlsym()的调用进程。
 * 使用dlclose()来卸载打开的库。
 * 头文件#include <dlfcn.h>
 * RTLD_LAZY:在dlopen返回前,对于动态库中的未定义的符号不执行解析
 * (只对函数引用有效,对于变量引用总是立即解析)。
 */
void *so = dlopen(path, RTLD_LAZY);
if (!so)
{
    std::cerr << dlerror() << std::endl;
    return false;
}

/* void* dlsym(void* handle,const char* symbol)
 * 根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的地址。
 * 使用这个函数不但可以获取函数地址,也可以获取变量地址。
 * handle:由dlopen打开动态链接库后返回的指针;
 * symbol:要求获取的函数或全局变量的名称。
 * SetupPlugin和RemovePlugin是插件模块中的函数;
 * SetupPlugin返回一个动态分配的插件对象;
 * RemovePlugin释放插件对象的内存空间。
 */
Plugin::SetupPlugin setup_plugin = (Plugin::SetupPlugin)dlsym(so, "SetupPlugin");

Plugin::RemovePlugin remove_plugin = (Plugin::RemovePlugin)dlsym(so, "RemovePlugin");

if (!setup_plugin || !remove_plugin)
{
    std::cerr << dlerror() << std::endl;
    dlclose(so);
    return false;
}

//根据上面取得的函数句柄,获取插件对象
Plugin *plugin = setup_plugin();

if (!plugin)
{
    //卸载打开的库
    dlclose(so);
    return false;
}

//……

return true;

以上是关于slighttpd基于lighttpd架构的Server项目实战(10)—插件&动态库的主要内容,如果未能解决你的问题,请参考以下文章

slighttpd基于lighttpd架构的Server项目实战—http-parser

slighttpd基于lighttpd架构的Server项目实战—状态机机制回顾

slighttpd基于lighttpd架构的Server项目实战(10)—插件&动态库

slighttpd基于lighttpd架构的Server项目实战—预备知识之Http

基于 Serverless 架构的编程学习小工具

基于 Serverless 架构的编程学习小工具