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

前端 未结 8 1993
失恋的感觉
失恋的感觉 2020-12-01 06:24

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 (func         


        
相关标签:
8条回答
  • 2020-12-01 06:56

    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"]();
     }
    
    0 讨论(0)
  • 2020-12-01 06:56

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

    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:

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

    To make things easy, let shorten the param type:

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

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

    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 (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.

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

    0 讨论(0)
  • 2020-12-01 06:59

    You can use #pragma weak for the compilers that support it (see the weak symbol wikipedia entry).

    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.

    0 讨论(0)
  • 2020-12-01 07:01

    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).

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

    0 讨论(0)
  • 2020-12-01 07:04

    While other replies are helpful advices (dlsym, function pointers, ...), you cannot compile C++ 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) defines the function, the linker would complain (unless it is weak, see below).

    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 dlsym often requires functions without name mangling, i.e. declared as extern "C".

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

    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 dlopen with a NULL path gives a handle to the main program, which you should link with -rdynamic to have it work correctly.

    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.

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

    0 讨论(0)
  • 2020-12-01 07:06

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

    #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:

    • 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 #define and things like that happen at compile time.

    ....

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

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

    0 讨论(0)
提交回复
热议问题