开发者

Can I re-define a function or check if it exists?

I have a question about (re-)defining functions. My goal is to have a script where I can choose to define a function or not. Li开发者_如何学运维ke this:

void func(){}

int main(){
   if (func)func();
}

AND without the function, just:

int main(){
   if (func)func();
}

Anybody an idea?


You can do this in GCC using its weak function attribute extension:

void func() __attribute__((weak)); // weak declaration must always be present

int main() {
  if (func) func();
  // ...
}

// optional definition:
void func() { ... }

This works even if func() is defined in another .c file or a library.


Something like this, I think. Haven't used function pointers much, so I may have gotten the syntax slightly wrong.

  void func()
  {
#define FUNC_PRESENT
      // code
  }

  void (*funcptr)();

#ifdef FUNC_PRESENT
      funcptr = func;
#else
      funcptr = NULL;
#endif

  int main()
  {
      if (funcptr)
          funcptr();
  }


Use function pointers, set them dynamically based on runtime conditions, and check for null pointers or wrap them in methods that do that check for you.

Only option in C I can think of.

In C++ you could combine templates and DLLs to dynamically define at runtime.


Really the only way that you can "choose to define a function or not" is with C preprocessor directives. For example:

#ifdef some_name
void func() {
    do_whatever();
}
#else
  //the else part is optional
#endif

To set these "variables" you use #define some_name

The trouble is, all of this needs to be done at compile time (before that, actually) so it can't be done with an if statement like in your example. If you want an if statement to control your program flow, just use it and don't bother with trying to rename functions or using function pointers or something.


Introduction

I guess that you are trying to do this:

  • Two modules, a.o and b.o
  • b.o contains a definition for void foo()
  • a.o calls void foo() only if b.o is also linked into the final executable.

This could be useful for a "plugin" system.


Variation 1

You can simulate it using function pointers. I don't know enough C to write this in proper C code, but pseudocode looks like this:

a.h

extern collectionOfFuncPtrs_t list;
int addFuncPtr();

a.c

#include "a.h"

collectionOfFuncPtrs_t list;
int addFuncPtr(FuncPtr p) {
   - add func ptr to list
   - return 0
}

int main() {
   - loop through list of function pointers
   - call functions through them
}

b.c

#include "a.h"

void bar() { /* ... */ }

static int dummy = addFuncPtr(&bar);

c.c

#include "a.h"

void ayb() { /* ... */ }

static int dummy = addFuncPtr(&ayb);

Conclusion

Now, you can link in b.o and/or c.o as you wish, and int main() will only call bar() and/or ayb() if they exist.


Variation 2

Experiment with variations on this theme if it looks like it may be useful to you. In particular, if you have only a specific number of conditionally-defined functions, you could use a bunch of individual function pointers rather than some list:

a.h

extern fptr_t bar_ptr, ayb_ptr;

a.c

#include "a.h"

int main() {
   if (bar_ptr)
      bar_ptr();
   if (ayb_ptr)
      ayb_ptr();
}

b.c

#include "a.h"

void bar() { /* ... */ }

fptr_t bar_ptr = &bar;

b_dummy.c

#include "a.h"
fptr_t bar_ptr = 0;

c.c

#include "a.h"

void ayb() { /* ... */ }

fptr_t ayb_ptr = &ayb;

c_dummy.c

#include "a.h"
fptr_t ayb_ptr = 0;

Conclusion

Now either link b.o or b_dummy.o; and either link c.o or c_dummy.o.

I hope you get the general idea, anyway...!


Bootnote

This is a lot easier in C++ where you can write a module registration system very easily with std::maps and constructors.


In C? Only by using the preprocessor as stated in other answers.

C isn't a dynamic language like, say, Python.


The right way to do what I think you're asking about in C is to use function pointers. You can take the address of a function, assign it to a variable, test it for nil, etc. However, plain old C isn't a very dynamic language; you might be better off using a different language.


if you don't mind compiler specific extension, you can use __if_exists:

#include <iostream>
using namespace std; 

// uncomment the following, and it'll still work
void maybeFunc(){ cout << "running maybe" << endl; }

int main(){
    cout << "hi!" << endl; 
    __if_exists(maybeFunc)
        cout << "maybe exists!" << endl; 
        maybeFunc(); 
    }
}

this works in msvc by default, and in clang if you use the -fms-extensions flag.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜