【问题标题】:Error codes and message handling in a plugin system插件系统中的错误代码和消息处理
【发布时间】:2012-07-27 11:56:37
【问题描述】:

我正在思考 C 项目中错误代码的最佳设计和相应的错误消息。该项目由一个提供核心功能的小内核组成,可以通过各种插件进行扩展。内核已经定义了最通用的错误代码,例如PROJ_NOERR(无错误)或 PROJ_ENOMEM(无可用内存)。此外,插件还应该能够定义特殊的错误代码及其相应的消息,例如Web 服务器插件可以定义 WEBSERV_ESOCKET(套接字错误)。在我看来,内核还应该提供将错误代码转换为相应错误消息的功能,例如extern char* proj_err2str(enum err_t);这个函数还应该能够处理所有加载插件的定义错误代码。您将如何实施这样的系统?欢迎任何提示!

提前致谢, /* 乔纳斯 */

【问题讨论】:

    标签: c plugins error-code


    【解决方案1】:

    我不太明白你的意思,但这里有一个关于如何创建插件的示例代码:

    /* This struct  is common to all plugins and the functions defined here must be implemented by all plugins*/
    typedef struct
    {
      int (*plugin_function_one) (char *str);
      void (*plugin_function_two) (int fd);
      void (*plugin_handle_error) (char *err, int status);
      char plugin_errors_codes[ERR_CODES_NUM]; // Each plugin can add errors code here
    } plugin_t;
    

    然后您可以创建一个插件(plugin_one),例如:

    int plugin_function_one(char *str)
    {
        // Body of function_one
    }
    
    void plugin_function_two(int fd)
    {
        Body of function_two
    }
    
    // Here you have your error handling function for plugin_one
    
    void plugin_handle_error(char *err, int status)
    {
        fprintf(stderr,"Plugin --> Got this error: %s and errno = %d", strerror(err), errno);
        // depend on status, we can exist or not for exampe
        if (status)
            exit(EXIT_FAILURE);
    }
    

    现在初始化你的插件:

    plugin_t * plugin_init (plugin_t * p)
    {
      /* Plugin init */
      p-> plugin_function_one = plugin_function_one;
      p-> plugin_function_two = plugin_function_two;
      p-> plugin_handle_error = plugin_handle_error;
    
      /* init the array of errors here */
      init_plugin_errors(p->plugin_errors_codes);
      /* return the newly created plugin */
      return (p);
    }
    

    您可以像这样加载和上传所有插件:

    int plugin_load (char *path_to_your_plugin)
    {
        void *dh;
        plugin_t *(*p_init) (plugin_t * p);
        plugin_t dp;
    
        /* opening plugin */
        dh = dlopen (path_to_your_plugin, RTLD_LAZY);
        if (NULL == dh)
        {
            fprintf (stderr,  "Failed to load '%s' (errno=%d, msg='%s')\n",path_to_your_plugin, errno, strerror (errno));
                exit (EXIT_FAILURE);
            }
    
        /* Now we look for plugin_init function */
         p_init = dlsym (dh, "plugin_init");
        if (NULL == p_init)
            {
                fprintf (stderr, "Failed to get 'plugin_init'\n");
                dlclose (dh);
                exit (EXIT_FAILURE);
            }
    
        /* We init the plugin */
        if (NULL == p_init (&dp))
            {
                fprintf (stderr, "Error plugin_init()\n");
                dlclose (dh);
                exit (EXIT_FAILURE);
            }
    
        …..
    
        /* Calling plugin functions */
        dp.plugin_handle_error(char *err, int status);
    }
    

    并卸载插件:

    int plugin_unload (char * path_to_your_plugin)
    {
        /* Need the address of the loaded plugin to call dlclose, let's call it the_address */
        if (the_adress != NULL)
            fprintf(stdout, "This plugin will be unloaded : %p", the_adress);
        /* close plugin. */
        dlclose (the_adress);
    
        return 0;
    }
    

    要处理不同插件之间的重复错误代码,函数 err2str 需要知道哪个插件正在提交请求:

    int err2str (plugin_t *plugin, int error_code)
    {
        // Lookup in the plugin_errors_codes array
        char *my_error;
        my_error = error_lookup(plugin->plugin_errors_codes, error_code);
        print_error(my_error); 
    }
    

    希望对您有所帮助。

    问候。

    【讨论】:

    • 感谢您的详细回答。我的问题不是关于插件管理器,而是针对错误处理功能。我希望插件可以定义自己的错误代码,这些代码在整个应用程序(内核和插件)中是唯一的。此外,我希望内核中的单个函数(err2str)可以处理所有定义的错误代码,也包括插件定义的错误代码。最好的问候!
    • @Jonas :对于错误代码,您可以创建一个数组来保存 struct 插件中的所有错误代码,每个插件都可以使用他的错误代码初始化这个数组。我将编辑我的答案以满足这一点。
    • 嗯,但在这种情况下,由两个不同插件定义的两个错误代码可以具有相同的错误代码值 (int)。还是我理解错了?我认为每个错误代码在所有插件中应该是唯一的。
    • 但也许我的想法/想象力只是毫无意义......我现在不确定......
    • @Jonas :这取决于你,你可以让所有插件中的所有错误代码都是唯一的,这很清楚,或者每个插件都可以添加它的错误代码,在这种情况下,函数 err2str 需要知道哪个插件正在调用,它可以引用它的代码数组,就像我向您展示的结构一样。我将编辑答案以添加此内容。
    猜你喜欢
    • 2019-04-05
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 2017-01-24
    相关资源
    最近更新 更多