Невозможно инициализировать массив со структурой, содержащей указатель на функцию - ошибка: элемент инициализатора не является константой

Я пытаюсь инициализировать массив структур. Структура содержит указатель на функцию в качестве одного из элементов данных. Но мой компилятор выдает ошибку, жалуясь на то, что элемент инициализатора не является константой. Как я могу инициализировать массив с объявленным указателем на функцию?

typedef void (*write_func_ptr_t)( void**, size_t*, char*, const size_t);
typedef bool (*read_func_ptr_t)( char*, const void*, const size_t);

write_func_ptr_t generate_basic_msg_ptr;
read_func_ptr_t handle_basic_msg_ptr;
write_func_ptr_t generate_reg_msg_ptr;
read_func_ptr_t handle_reg_msg_ptr;

struct supported_msg_info
{
    const char* const type;
    const write_func_ptr_t write_func;
    const read_func_ptr_t read_func;
};

static struct supported_msg_info SUPP_MESSAGES[] = {
    { "basic", generate_basic_msg_ptr, handle_basic_msg_ptr },
    { "registration", generate_reg_msg_ptr, handle_reg_msg_ptr }
};

person agranum    schedule 20.02.2015    source источник
comment
Инициализаторы в C не могут содержать изменяемые переменные, в том числе указатели на функции. Даже если бы они были объявлены const, они все равно не работали бы, потому что правила инициализации C очень строги.   -  person Austin Mullins    schedule 20.02.2015
comment
Что ты пытаешься сделать? где определения функций?   -  person Iharob Al Asimi    schedule 20.02.2015
comment
Определения функций будут загружаться во время выполнения из общей библиотеки с помощью dlsym.   -  person agranum    schedule 20.02.2015


Ответы (2)


Вы можете сделать это, добавив объявления функций и сопоставив их с типами указателей функций, как это

void generate_basic_msg_ptr(void **, size_t *, char *, const size_t);
bool handle_basic_msg_ptr(char *, const void *, const size_t);
void generate_reg_msg_ptr(void **, size_t *, char *, const size_t);
bool handle_reg_msg_ptr(char *, const void *, const size_t);

Но судя по вашему комментарию

Определения функций будут загружаться во время выполнения из общей библиотеки с помощью dlsym — agranum 59 секунд назад

Что вам действительно нужно, так это

struct supported_msg_info
{
    const char *const type;
    /* remove the const qualifier */
    write_func_ptr_t write_func;
    read_func_ptr_t read_func;
};

static struct supported_msg_info SUPP_MESSAGES[] = {
    {"basic", NULL, NULL},
    {"registration", NULL, NULL}
};

а затем, когда вы позвоните dlsym, вы можете сделать это

SUPP_MESSAGES[0].write_func = dlsym(dlhandle, "symbol_name");

тогда функция SUPP_MESSAGES[0].write_func будет вызываться с сигнатурой, заданной вашим определением struct, и указателями функций typedef, и помните, что void * можно преобразовать в любой тип указателя без приведения, так что это все, что вам нужно.

person Iharob Al Asimi    schedule 20.02.2015
comment
Ваше первоначальное решение на самом деле заставило меня задуматься о том, что было бы неплохо иметь реализацию функций по умолчанию в этом файле c в качестве запасного варианта на случай, если реализация не существует в .so, на которую я буду ссылаться во время выполнения. Таким образом, я мог бы выдать сообщение о том, что его там нет, и не сбой. Спасибо. - person agranum; 20.02.2015

generate_basic_msg_ptr и друзья - это просто переменные, которые даже не инициализированы (ну, строго говоря, они могли быть инициализированы нулями, но это, вероятно, не ваше намерение). Таким образом, они не имеют определенных значений во время компиляции и, очевидно, не могут использоваться для инициализации массива. Возможно, вы захотите объявить такие функции, как void func(<whatever>);, и использовать func при инициализации.

person Eugene Sh.    schedule 20.02.2015