如何检查C/C++中是否存在该函数

Who*_*ami 22 c c++ linux

在我的代码中的某些情况,我最终只在定义了该函数时调用该函数,否则我不应该.我怎样才能实现这一目标?

like:
if (function 'sum' exists ) then invoke sum ()
Run Code Online (Sandbox Code Playgroud)

可能是另一种方式来问这个问题是:如何确定函数是否在运行时定义,如果是,则调用.

mat*_*tiu 13

当你声明'sum'时,你可以声明它:

#define SUM_EXISTS
int sum(std::vector<int>& addMeUp) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

然后,当你来使用它时,你可以去:

#ifdef SUM_EXISTS
int result = sum(x);
...
#endif
Run Code Online (Sandbox Code Playgroud)

我猜你是来自一种脚本语言,其中的一切都是在运行时完成的.使用C++需要记住的主要问题是两个阶段:

  • 编译时间
    • 预处理器运行
    • 模板代码变成了真正的源代码
    • 源代码在机器代码中打开
  • 运行
    • 机器代码运行

所以所有这些#define事情都发生在编译时.

....

如果您真的想在运行时完成所有这些操作,那么您可能会对使用某些组件架构产品感兴趣.

或者也许是插件式的架构就是你所追求的.

  • C++ 还没有在标准中包含这样的编译指示,这是非常愚蠢的。C++ 头文件通常包含无数的 hacks 来处理这个问题。giid 规范甚至可以是特定于类型的。#ifhave(sum(std::vector))。我会为了那一项功能废弃所有的 C++11... (3认同)

Bru*_*Adi 10

使用指向函数的指针.

 //initialize
 typedef void (*PF)();
 std::map<std::string, PF> defined_functions;
 defined_functions["foo"]=&foo;
 defined_functions["bar"]=&bar;
 //if defined, invoke it
 if(defined_functions.find("foo") != defined_functions.end())
 {
     defined_functions["foo"]();
 }
Run Code Online (Sandbox Code Playgroud)


Bas*_*tch 10

虽然其他回复是有用的建议(dlsym,函数指针,...),但您无法编译引用不存在的函数的C++代码.至少,必须声明该功能; 如果不是,您的代码将无法编译.如果没有(编译单元,某些目标文件,某些库)定义函数,链接器会抱怨(除非它很弱,见下文).

但是你应该解释为什么要问这个问题.我无法猜测,并且有一些方法可以达到你未说明的目标.

请注意,dlsym通常需要没有名称修改的函数,即声明为extern "C".

如果在使用GCC的Linux上编码,您也可以在声明中使用weak 函数属性.然后,链接器将未定义的弱符号设置为null.

附加物

如果你从某个输入中获取函数名,你应该知道只有一部分函数应该以这种方式调用(如果你不小心调用任意函数,它会崩溃!)你最好明确地构造那个子集.然后std::map,您可以使用a 或dlsym(声明子集中的每个函数extern "C").请注意,dlopen使用NULL路径提供主程序的句柄,您应链接该程序-rdynamic以使其正常工作.

你真的想通过他们的名字只调用一个适当定义的函数子集.例如,你可能不希望把这种方式abort,exitfork.

NB.如果您动态了解被调用函数的签名,则可能需要使用libffi来调用它.

  • 使用模板的C++(尽管不是C)SFINAE的另一种方法:http://stackoverflow.com/questions/257288/is-it-possible-to-write-ac-template-to-check-for-a-functions-existence (4认同)

fre*_*aba 10

我怀疑海报实际上是在寻找SFINAE检查/派遣的更多内容.使用C++模板,可以定义模板函数,一个调用所需函数(如果存在)和一个不执行任何函数(如果函数不存在).然后,您可以使第一个模板取决于所需的函数,以便在函数不存在时模板格式错误.这是有效的,因为在C++模板中,替换失败不是错误(SFINAE),因此编译器将回退到第二种情况(例如它什么都不做).

请看这里有一个很好的例子:是否可以编写模板来检查函数的存在?

  • 这适用于 printf 等顶级函数吗? (3认同)

小智 8

使用GCC您可以:

void func(int argc, char *argv[]) __attribute__((weak)); // weak declaration must always be present

// optional definition:
/*void func(int argc, char *argv[]) { 
    printf("ENCONTRE LA FUNC\n");
    for(int aa = 0; aa < argc; aa++){
        printf("arg %d = %s \n", aa, argv[aa]);
    }
}*/

int main(int argc, char *argv[]) {
    if (func){ 
        func(argc, argv); 
    } else {
        printf("no encontre la func\n");
    }
}
Run Code Online (Sandbox Code Playgroud)

如果取消注释func,它将运行它,否则它将打印"no encontre la func \n".

  • 我将西班牙语原文翻译成英语,以防止此回复被标记为非英语内容 [非英语指南](https://meta.stackoverflow.com/questions/297673/how-do-i-deal -带有非英语内容)。原文“ENCONTRE LA FUNC”和“no encontre la func”对于一些说英语的人来说并不清楚。 (3认同)

Tim*_*nes 5

如果您知道要调用的函数位于哪个库中,则可以使用dlsym()dlerror()找出它是否在其中,以及指向该函数的指针。

编辑:我可能实际上不会使用这种方法-相反,我会推荐Matiu的解决方案,因为我认为这是更好的做法。但是,dlsym()并不是很知名,所以我想指出这一点。


mih*_*hai 5

您可以使用#pragma weak支持它的编译器(请参阅弱符号维基百科条目)。

这个例子和评论来自共享库和动态加载的内幕

#pragma weak debug
extern void debug(void);
void (*debugfunc)(void) = debug;
int main() {
    printf(“Hello World\n”);
    if (debugfunc) (*debugfunc)();
}
Run Code Online (Sandbox Code Playgroud)

您可以使用弱编译指示来强制链接器忽略未解析的符号 [..] 程序编译和链接无论 debug() 实际上是否在任何目标文件中定义。当符号未定义时,链接器通常用 0 替换它的值。因此,这种技术对于程序调用不需要重新编译整个应用程序的可选代码是一种有用的方法。