4

I want to create a function wrapper, with a defined body, that calls the wrapped function.

How can I get from this:

int foo (int arg)
{ 
   do_something(arg);
}

To something equivalent to this:

int foo (int arg)
{
   always_do_this();
   real_foo(arg);
}
int real_foo (int arg)
{ 
   do_something(arg);
}  

I must do the transformation automatically and it has to be signature independent and in compile time.

How can I do it?

Felipe Lavratti
  • 2,887
  • 16
  • 34
  • write some code doing it? Parse the code file and transform it the way you need it. – Theolodis Apr 30 '14 at 15:51
  • This answer may be helpful: [Automatically adding Enter/Exit Function Logs to a Project](http://stackoverflow.com/a/2291426/1004301) – Lee Duhem Apr 30 '14 at 16:16

2 Answers2

2

You can do this with macros, here's a quick example:

#define CREATE_FUNC_WRAPPER(NAME, ARG)      \
    int NAME(ARG arg) {         \
        real_##NAME(arg);       \
    }

int real_foo(int a) {
    printf("real_foo speaking: %d\n", a);
}

CREATE_FUNC_WRAPPER(foo, int)

int main() {
    foo(1);
}

You need to modify it to fit your needs, your question is unclear.

  • What if there are more than one argument? – Felipe Lavratti Apr 30 '14 at 15:56
  • 1
    Well, you could do multiple macros of this, or use `...` as parameter in the macro `#define CREATE_FUNC_WRAPPER(NAME, ...)` and unpack with `##args` or `__VA_ARGS__` –  Apr 30 '14 at 15:58
2

I had to give up from installing wrapper on function declaration, the solution was to install the wrappers on function call using compound statements. Bellow the two macros I created to do that, one deals with calls returning void, other with any call that returns a value:

#define PROFILE_VOID(call) \
({ \
  hal_time_t stop, start; \
  hal_getTime(&start); \
  call; \
  hal_getTime(&stop); \
  __PROFILE_PRINT(call, hal_secondsElapsed_d(&stop, &start)); \
})

#define PROFILE(call) \
({ \
  typeof(call) __ret; \
  hal_time_t stop, start; \
  __profile_nested_cnt++; \
  hal_getTime(&start); \
  __ret = call; \
  hal_getTime(&stop); \
  __profile_nested_cnt--; \
  __PROFILE_PRINT(call, hal_secondsElapsed_d(&stop, &start)); \
  __ret; \
})

Example of use:

PROFILE_VOID(func_returning_void(arg, arg2)); //Void func
PROFILE(other_funcs());  // Any non void func
PROFILE(x = func(x, y, z));  //Any statement
x = PROFILE(func(x, y, z));  //Same as previous
if (PROFILE(func()) == 0) { } //Inside conditionals
if (PROFILE(func() == 0)) { } //Same as previous
Felipe Lavratti
  • 2,887
  • 16
  • 34