Linux 如何检查函数是否存在于 C/C++

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8814705/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:00:59  来源:igfitidea点击:

How to Check if the function exists in C/C++

c++clinux

提问by Whoami

Certain situations in my code, i end up invoking the function only if that function is defined, or else i should not. How can i achieve this ?

在我的代码中的某些情况下,我最终只有在定义了该函数时才调用该函数,否则我不应该调用该函数。我怎样才能做到这一点?

like:
if (function 'sum' exists ) then invoke sum ()

May be the other way around to ask this question is: How to determine if function is defined at runtime and if so, then invoke.

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

采纳答案by Basile Starynkevitch

While other replies are helpful advices (dlsym, function pointers, ...), you cannot compileC++ code referring to a function which does not exist. At minimum, the function has to be declared; if it is not, your code won't compile. If nothing (a compilation unit, some object file, some library) definesthe function, the linker would complain (unless it is weak, see below).

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

But you should really explain why you are asking that. I can't guess, and there is some way to achieve your unstated goal.

但是你真的应该解释你为什么这么问。我无法猜测,有一些方法可以实现您未说明的目标。

Notice that dlsymoften requires functions without name mangling, i.e. declared as extern "C".

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

If coding on Linux with GCC, you might also use the weakfunction attributein declarations. The linker would then set undefined weak symbols to null.

如果使用 GCC 在 Linux 上编码,您还可以在声明中使用weakfunction 属性。然后链接器会将未定义的弱符号设置为空。

addenda

附加物

If you are getting the function name from some input, you should be aware that only a subset of functions should be callable that way (if you call an arbitrary function without care, it will crash!) and you'll better explicitly construct that subset. You could then use a std::map, or dlsym(with each function in the subset declared extern "C"). Notice that dlopenwith a NULLpath gives a handle to the main program, which you should link with -rdynamicto have it work correctly.

如果您从某个输入中获取函数名称,您应该意识到只有一部分函数可以通过这种方式调用(如果您不小心调用任意函数,它将崩溃!)并且您最好明确地构造该子集. 然后std::map,您可以使用, 或dlsym(子集中声明的每个函数extern "C")。请注意,dlopen有一个NULL路径给出了一个手柄主程序,你应该与链接-rdynamic有它正常工作。

You really want to call by their name only a suitably defined subset of functions. For instance, you probably don't want to call this way abort, exit, or fork.

您真的只想通过它们的名称调用一个适当定义的函数子集。例如,你可能不希望把这种方式abortexitfork

NB. If you know dynamicallythe signature of the called function, you might want to use libffito call it.

注意。如果您动态知道被调用函数的签名,您可能希望使用libffi来调用它。

回答by Timothy Jones

If you know what library the function you'd like to call is in, then you can use dlsym()and dlerror()to find out whether or not it's there, and what the pointer to the function is.

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

Edit: I probably wouldn't actually use this approach - instead I would recommend Matiu's solution, as I think it's much better practice. However, dlsym()isn't very well known, so I thought I'd point it out.

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

回答by BruceAdi

use pointers to functions.

使用指向函数的指针。

 //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"]();
 }

回答by matiu

When you declare 'sum' you could declare it like:

当您声明 'sum' 时,您可以将其声明为:

#define SUM_EXISTS
int sum(std::vector<int>& addMeUp) {
    ...
}

Then when you come to use it you could go:

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

#ifdef SUM_EXISTS
int result = sum(x);
...
#endif

I'm guessing you're coming from a scripting language where things are all done at runtime. The main thing to remember with C++ is the two phases:

我猜你来自一种脚本语言,所有事情都是在运行时完成的。使用 C++ 需要记住的主要事情是两个阶段:

  • Compile time
    • Preprocessor runs
    • template code is turned into real source code
    • source code is turned in machine code
  • runtime
    • the machine code is run
  • 编译时间
    • 预处理器运行
    • 模板代码变成真正的源代码
    • 源代码转成机器码
  • 运行
    • 机器码运行

So all the #defineand things like that happen at compile time.

所以所有#define类似的事情都在编译时发生。

....

....

If you really wanted to do it all at runtime .. you might be interested in using some of the component architecture productsout there.

如果您真的想在运行时完成这一切……您可能对使用一些组件架构产品感兴趣。

Or maybe a plugin kind of architectureis what you're after.

或者,也许您所追求的是一种插件式架构

回答by fredbaba

I suspect that the poster was actually looking for something more along the lines of SFINAE checking/dispatch. With C++ templates, can define to template functions, one which calls the desired function (if it exists) and one that does nothing (if the function does not exist). You can then make the first template depend on the desired function, such that the template is ill-formed when the function does not exist. This is valid because in C++ template substitution failure is not an error (SFINAE), so the compiler will just fall back to the second case (which for instance could do nothing).

我怀疑海报实际上是在寻找更多类似于 SFINAE 检查/调度的东西。使用 C++ 模板,可以定义模板函数,一个调用所需的函数(如果存在),另一个什么都不做(如果函数不存在)。然后,您可以使第一个模板依赖于所需的函数,这样当函数不存在时模板就是格式错误的。这是有效的,因为在 C++ 中模板替换失败不是错误(SFINAE),所以编译器只会退回到第二种情况(例如什么都不做)。

See here for an excellent example: Is it possible to write a template to check for a function's existence?

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

回答by matiu

So another way, if you're using c++11 would be to use functors:

所以另一种方式,如果你使用 c++11 将使用函子:

You'll need to put this at the start of your file:

您需要将其放在文件的开头:

#include <functional>

The type of a functor is declared in this format:

函子的类型以这种格式声明:

std::function< return_type (param1_type, param2_type) >

You could add a variable that holds a functor for sum like this:

您可以添加一个变量来保存 sum 的函子,如下所示:

std::function<int(const std::vector<int>&)> sum;

To make things easy, let shorten the param type:

为了让事情变得简单,让我们缩短 param 类型:

using Numbers = const std::vectorn<int>&;

Then you could fill in the functor var with any one of:

然后你可以用以下任何一种填充函子 var:

A lambda:

一个拉姆达:

sum = [](Numbers x) { return std::accumulate(x.cbegin(), x.cend(), 0); } // std::accumulate comes from #include <numeric>

A function pointer:

一个函数指针:

int myFunc(Numbers nums) {
    int result = 0;
    for (int i : nums)
        result += i;
    return result;
}
sum = &myFunc;

Something that 'bind' has created:

“绑定”创建的东西:

struct Adder {
    int startNumber = 6;
    int doAdding(Numbers nums) {
        int result = 0;
        for (int i : nums)
            result += i;
        return result;
    }
};
...
Adder myAdder{2}; // Make an adder that starts at two
sum = std::bind(&Adder::doAdding, myAdder);

Then finally to use it, it's a simple if statement:

然后最后使用它,这是一个简单的 if 语句:

if (sum)
    return sum(x);


In summary, functors are the new pointer to a function, however they're more versatile. May actually be inlined if the compiler is sure enough, but generally are the same as a function pointer.

总之,函子是指向函数的新指针,但它们更通用。如果编译器足够确定,实际上可能会被内联,但通常与函数指针相同。

When combined with std::bind and lambda's they're quite superior to old style C function pointers.

当与 std::bind 和 lambda 结合使用时,它们比旧式 C 函数指针要好得多。

But remember they work in c++11 and above environments. (Not in C or C++03).

但请记住,它们在 c++11 及以上环境中工作。(不在 C 或 C++03 中)。

回答by mihai

You can use #pragma weakfor the compilers that support it (see the weak symbolwikipedia entry).

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

This example and comment is from The Inside Story on Shared Libraries and Dynamic Loading:

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

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

you can use the weak pragma to force the linker to ignore unresolved symbols [..] the program compiles and links whether or not debug() is actually defined in any object file. When the symbol remains undefined, the linker usually replaces its value with 0. So, this technique can be a useful way for a program to invoke optional code that does not require recompiling the entire application.

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

回答by Jose Luis Quiroga Beltran

Using GCC you can:

使用 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");
    }
}

If you uncomment func it will run it otherwise it will print "no encontre la func\n".

如果您取消注释 func,它将运行它,否则它将打印“no encontre la func\n”。