1

Automatically generate the function pointer table in C

 2 years ago
source link: https://www.codesd.com/item/automatically-generate-the-function-pointer-table-in-c.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Automatically generate the function pointer table in C

advertisements

I'm looking for a way to automatically (as part of the compilation/build process) generate a "table" of function pointers in C.

Specifically, I want to generate an array of structures something like:

typedef struct {
  void (*p_func)(void);
  char * funcName;
} funcRecord;

/* Automatically generate the lines below: */

extern void func1(void);
extern void func2(void);
/* ... */

funcRecord funcTable[] =
{
  { .p_func = &func1, .funcName = "func1" },
  { .p_func = &func2, .funcName = "func2" }
  /* ... */
};

/* End automatically-generated code. */

...where func1 and func2 are defined in other source files.

So, given a set of source files, each of which which contain a single function that takes no arguments and returns void, how would one automatically (as part of the build process) generate an array like the one above that contains each of the functions from the files? I'd like to be able to add new files and have them automatically inserted into the table when I re-compile.

I realize that this probably isn't achievable using the C language or preprocessor alone, so consider any common *nix-style tools fair game (e.g. make, perl, shell scripts (if you have to)).

But Why?

You're probably wondering why anyone would want to do this. I'm creating a small test framework for a library of common mathematical routines. Under this framework, there will be many small "test cases," each of which has only a few lines of code that will exercise each math function. I'd like each test case to live in its own source file as a short function. All of the test cases will get built into a single executable, and the test case(s) to be run can be specified on the command line when invoking the executable. The main() function will search through the table and, if it finds a match, jump to the test case function.

Automating the process of building up the "catalog" of test cases ensures that test cases don't get left out (for instance, because someone forgets to add it to the table) and makes it very simple for maintainers to add new test cases in the future (just create a new source file in the correct directory, for instance).

Hopefully someone out there has done something like this before. Thanks, StackOverflow community!


Using macros

How about making a macro list as

#define FUNC_LIST \
  FUNC( func1 ) \
  FUNC( func2 ) \
  FUNC( func3 ) \
  FUNC( func4 ) \
  FUNC( func5 )

and then expand the extern definitions as

#define FUNC( _name ) extern void _name(void);

FUNC_LIST

#undef FUNC

and then expand the table as

#define FUNC( _name ) { .p_func = &_name, .funcName = #_name },

funcRecord funcTable[] = {
  FUNC_LIST
};

#undef FUNC

Using dlsym(..)

If you have a strict naming convention for you test functions another suggestion is to look into using the function dlsym with the handle set to RTLD_DEFAULT and write a function that tries to look upp all functions at startup.

Example

#include <stdio.h>
#include <dlfcn.h>

void test2() {
  printf("Second place is the first loser!\n");
}

void test42() {
  printf("Read The Hitchhikers Guide To The Galaxy!\n");
}

int main() {
  int i;
  for (i=1; i<100; i++) {
    char fname[32];
    void (*func)();
    sprintf(fname, "test%d", i);
    func = dlsym(RTLD_DEFAULT, fname);
    if (func)
      func();
  }
  return 0;
}




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK