2015-11-01 112 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); 
}