2015-11-01 4 views
2

Я хочу позвонить функции в соответствии с func_name строка. Мой код здесь ниже:Как использовать макрос для вызова функции?

#define MAKE_FUNCNAME func_name##hello 

void call_func(void* (*func)(void)) 
{ 
    func(); 
} 

void *print_hello(void) 
{ 
    printf("print_hello called\n"); 
} 

int main(void) 
{ 
    char func_name[30] = "print_"; 

    call_func(MAKE_FUNCNAME); 
    return 0; 
} 

Но этот код не работает. Я хочу, чтобы код работал как call_func(print_hello). Но препроцессор обработал мой код как call_func("print_hello"). Как использовать макрос в C, чтобы сделать мое исключение? Или это невозможно, используя C?

+1

Я думаю, что это не должен возможно. После того, как эта программа будет скомпилирована в двоичную исполняемую программу без какой-либо информации метки (для отладки), как система должна знать правильную функцию для вызова? – MikeCAT

+0

Невозможно с макросом, по крайней мере, самостоятельно. Было бы возможно создать какое-то сопоставление между строками и указателями функций. Единственный способ - это макрос, который расширяется до набора операторов (включая, возможно, вызовы функций), с тем, что отображение выполняется во время выполнения. – Peter

ответ

2

Вы не можете этого сделать. Значение func_name известно во время выполнения (хотя это const char *), в то время как вы хотите определить, что вызывать в прекомпиляцию. Вы должны превратить макрос cpp в нечто другое (например, оператор if/switch или использование косвенности).

4

Тогда проблема с вашим кодом в том, что значение func_name известно только во время выполнения.

Вы можете, однако, это так:

#define MAKE_FUNCNAME(FUNCNAME) FUNCNAME##hello 

void call_func(void* (*func)(void)) 
{ 
    func(); 
} 

void *print_hello(void) 
{ 
    printf("print_hello called\n"); 
} 

int main(void) 
{ 
    call_func(MAKE_FUNCNAME(print_)); 
    return 0; 
} 

Но это не представляется возможным использовать значение строки в пределах макро параметров, как в вашем фрагменте кода.

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

struct { 
    const char *name; 
    void (*ptr)(void); 
}; 

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

1

Возможно, вы могли бы взглянуть на dlsym().

Не уверен, что я действительно понял вопрос, но если вы хотите, чтобы «построить» имя функции во время выполнения, а затем вызвать соответствующую функцию, она должна быть возможно с dlsym()

/* compile with: gcc example.c -ldl -rdynamic */ 
#include <dlfcn.h> 
#include <stdio.h> 

int print_hello(void) 
{ 
    return printf("hello\n"); 
} 

int main(int argc, char *argv[]) 
{ 
    const char *name = "print_hello"; 
    if (argc == 42) 
     print_hello(); /* for compiler not to remove print_hello at 
         * compile time optimisation in this example*/ 
    void *handle = dlopen(NULL /* self */, RTLD_NOW); 
    int (*f)(void) = dlsym(handle, name); 
    f(); 
    return dlclose(handle); 
} 
Смежные вопросы