【问题标题】:Apache module command parser prototypeApache 模块命令解析器原型
【发布时间】:2015-05-24 15:07:22
【问题描述】:

我正在创建一个 Apache2 模块并遇到一个奇怪的编译问题。 这是我用于解析名为“analytics_ip”的配置命令的函数原型:

static const char *apr_cfg_set_analytics_ip(cmd_parms *cmd, void *config, const char *data);

这是 command_rec 结构的数组,其中包含指向此函数的指针:

static const command_rec apr_cmds[] =
{
 AP_INIT_TAKE1("analytics_ip", apr_cfg_set_analytics_ip, NULL, OR_ALL, ""),
 { NULL }
};

结构command_rec在头文件http_config.h

中声明
typedef struct command_struct command_rec;
struct command_struct {
    /** Name of this command */
    const char *name;
    /** The function to be called when this directive is parsed */
    cmd_func func;
    /** Extra data, for functions which implement multiple commands... */
    void *cmd_data;
    /** What overrides need to be allowed to enable this command. */
    int req_override;
    /** What the command expects as arguments */
    enum cmd_how args_how;

    /** 'usage' message, in case of syntax errors */
    const char *errmsg;
};

当我关注 cmd_func 时,它会得到以下声明:

typedef const char *(*cmd_func) ();

如果我没记错的话,这意味着“指向函数的指针返回指向 char 的指针并且不接受任何参数”。这怎么可能?命令解析函数必须接受至少一个参数,该参数包含该函数对应的配置变量的模块值。

我正在使用 g++ 来编译这个模块。 错误信息:

mod_xxx.h:65:2: error: invalid conversion from ‘const char* (*)(cmd_parms*, void*, const char*) {aka const char* (*)(cmd_parms_struct*, void*, const char*)}’ to ‘cmd_func {aka const char* (*)()}’ [-fpermissive]
  };

提前致谢

【问题讨论】:

    标签: c++ c linux apache apache-modules


    【解决方案1】:

    cmd_func是一个联合,在http_config.h中定义如下:

    typedef union {
        /** function to call for a no-args */
        const char *(*no_args) (cmd_parms *parms, void *mconfig);
        /** function to call for a raw-args */
        const char *(*raw_args) (cmd_parms *parms, void *mconfig,
                                 const char *args);
        /** function to call for a argv/argc */
        const char *(*take_argv) (cmd_parms *parms, void *mconfig,
                                 int argc, char *const argv[]);
        /** function to call for a take1 */
        const char *(*take1) (cmd_parms *parms, void *mconfig, const char *w);
        /** function to call for a take2 */
        const char *(*take2) (cmd_parms *parms, void *mconfig, const char *w,
                              const char *w2);
        /** function to call for a take3 */
        const char *(*take3) (cmd_parms *parms, void *mconfig, const char *w,
                              const char *w2, const char *w3);
        /** function to call for a flag */
        const char *(*flag) (cmd_parms *parms, void *mconfig, int on);
    } cmd_func;
    

    enum cmd_how args_how;负责选择正确的函数版本。

    处理它的开关位于server/config.c(在invoke_cmd函数中)。

    您似乎使用的是对应于cmd->AP_TAKE1 或简单的cmd->take1 的“take1”版本。

    问题可能是 C 和 C++ 有differences regarding the union initialization。 (AP_INIT_TAKE1 使用 { .take1=func } 语法,这在 C++ 中不起作用)。

    您必须以与 C++ 兼容的方式初始化 static const command_rec apr_cmds,或将其移动到使用 C 编译的单独目标文件中。或者,如果您不使用 C++,则只需使用 gcc 进行编译。

    【讨论】:

    • 我通过破解 http_config.h #ifdef __cplusplus typedef const char *(*cmd_func) (cmd_parms *cmd, void *dummy, const char *path) 解决了问题; #else typedef const char *(*cmd_func) (); #endif
    • 哦,这么近!我在 ... #ifdef __cplusplus typedef const char *(*cmd_func) (cmd_parms *cmd, void *dummy, ...); #else typedef const char *(*cmd_func) (); #endif
    【解决方案2】:

    对于我正在处理的项目,我们最终添加了一个强制转换以允许编译成功完成,并且代码似乎可以正常工作,因为它正确读取了配置文件中指定的值。这是这种做法的摘录: extern "C" { static const command_rec kiwix_settings[] = { AP_INIT_TAKE1("zimFile", (const char* (*)())kiwix_set_zimfilename, NULL, RSRC_CONF, "The ZIM filename in full including the extension"), AP_INIT_TAKE1("zimPath", (const char* (*)())kiwix_set_path, NULL, RSRC_CONF, "The path to the ZIM file, including the trailing //"), { NULL } }; }

    完整的文件(实际上是项目)是开源的。这是完整文件的链接https://github.com/kiwix/kiwix-apache/blob/master/mod_kiwix.cpp

    PS:感谢您的问题和https://stackoverflow.com/users/257568/artemgr 的回答,因为他们帮助我和另一位志愿者解决了我们项目的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      相关资源
      最近更新 更多