2015-02-20 3 views
0

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

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 } 
}; 
+0

Инициализаторы в C не могут содержать изменяемые переменные, включая указатели на функции. Даже если они были объявлены 'const', они все равно не будут работать, потому что правила инициализации C очень строги. –

+0

Что вы пытаетесь сделать? где - определения функций? –

+0

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

ответ

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); 

Но согласно вашим комментарием

The definitions of the functions are going to be pulled in at runtime from a shared library using dlsym – agranum 59 secs ago

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

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"); 

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

+0

. Ваше первоначальное решение фактически заставило меня думать, что было бы хорошо иметь реализацию функций по умолчанию в этом c-файле как резервную в случае, если реализации не было в .so, с которым я бы связывался во время выполнения. Таким образом, я мог выплюнуть сообщение, указывающее, что его нет и не сбой. Благодарю. – agranum

0

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