【问题标题】:How to use macro for calling function?如何使用宏来调用函数?
【发布时间】:2016-05-30 06:50:54
【问题描述】:

我想根据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

【问题讨论】:

  • 我认为这应该是不可能的。这个程序编译成没有任何标签信息的二进制可执行程序(用于调试)后,系统如何知道调用的正确函数呢?
  • 使用宏是不可能的,至少就其本身而言是不可能的。可以在字符串和函数指针之间创建某种映射。唯一的方法是使用一个宏,该宏扩展为一组语句(可能包括函数调用),结果是在运行时完成映射。

标签: c macros c-preprocessor


【解决方案1】:

那么你的代码的问题是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;
}

但是不能像在你的代码 sn-p 中那样在宏参数中使用字符串值。

如果您想使用字符串值获取调用函数的名称,您可以使用表来存储函数指针,函数名称如下:

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

您可以使用此结构的数组在运行时使用字符串值查找函数指针。这是使用运行时字符串通过函数名称调用函数的最常见解决方案。

【讨论】:

    【解决方案2】:

    你不能那样做。 func_name 的值在运行时是已知的(即使它是一个 const char *),而您想确定在预编译时调用什么。你应该把你的 cpp 宏变成不同的东西(比如 if/switch 语句或使用间接)。

    【讨论】:

      【解决方案3】:

      也许你可以看看 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);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-28
        • 1970-01-01
        相关资源
        最近更新 更多