Прототип парсера команд модуля Apache

Я создаю модуль Apache2 и испытываю странную проблему компиляции.
Это прототип моей функции, используемой для разбора команды config с именем «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) ();

Если я не ошибаюсь, это означает «указатель на функцию, возвращающую указатель на символ и не принимающий никаких аргументов». Как это может быть возможным? Функция синтаксического анализа команды должна принимать хотя бы один параметр, содержащий значение модуля переменной конфигурации, соответствующей этой функции.

Я использую 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]
};

заранее спасибо

3

Решение

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; отвечает за выбор правильной версии функции.

Переключатель, обрабатывающий его, находится в Сервер / config.cinvoke_cmd функция).

Вы, кажется, используете версию «take1», которая соответствует cmd->AP_TAKE1 или просто cmd->take1,

Проблема может заключаться в том, что C и C ++ имеют различия относительно инициализации объединения. (AP_INIT_TAKE1 использует { .take1=func } синтаксис, который не работает в C ++).

Вам придется инициализировать static const command_rec apr_cmds совместимым с C ++ способом или переместите его в отдельный объектный файл, скомпилированный с C. Или, если вы не используете C ++, просто скомпилируйте с gcc,

3

Другие решения

Для проекта, над которым я работаю, мы закончили тем, что добавили приведение, чтобы компиляция успешно завершилась, и код, кажется, работает нормально, поскольку он правильно читает значения, указанные в файле конфигурации. Вот выдержка из этой практики:

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Ответ, поскольку они помогли мне и другому добровольцу решить, как решить проблему для нашего проекта.

0