Apache module command parser prototype

旧巷老猫 提交于 2020-01-01 17:12:03

问题


I am creating an Apache2 module and experiencing a weird compilation problem. This is prototype of my function used to parse config command named "analytics_ip":

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

This is array of command_rec structures containing pointers to this function:

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

Structure command_rec is declared in header file 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;
};

When I follow cmd_func, it gets to the following declaration:

typedef const char *(*cmd_func) ();

If I am not mistaken, this means "pointer to function returning pointer to char and not accepting any arguments". How can this be possible? Command parsing function has to accept at least one parameter containing a module value of config variable corresponding to that function.

I am using g++ to compile this module. Error message:

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]
  };

Thanks in advance


回答1:


cmd_func is a union, it is defined in http_config.h as follows:

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; is responsible for choosing the correct version of the function.

The switch handling it is located in server/config.c (in the invoke_cmd function).

You seem to be using the "take1" version which corresponds to cmd->AP_TAKE1 or simply cmd->take1.

The problem might be that C and C++ have differences regarding the union initialization. (AP_INIT_TAKE1 uses the { .take1=func } syntax which doesn't work in C++).

You'll have to initialize static const command_rec apr_cmds in a C++-compatible way or move it to a separate object file compiled with C. Or if you're not using C++ then simply compile with gcc.




回答2:


For the project I'm working on we ended up adding a cast to allow the compilation to complete successfully, and the code seems to work OK as it correctly reads in the values specified in the configuration file. Here's the extract of this practice: 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 } }; }

The full file (and indeed the project) are opensourced. Here's the link to the full file https://github.com/kiwix/kiwix-apache/blob/master/mod_kiwix.cpp

PS: thanks for your question and https://stackoverflow.com/users/257568/artemgr's answer as they helped me and another volunteer to work out how to resolve the problem for our project.



来源:https://stackoverflow.com/questions/30424979/apache-module-command-parser-prototype

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!