Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatically generate table of function pointers in C

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!

like image 215
jeremytrimble Avatar asked Mar 19 '10 21:03

jeremytrimble


2 Answers

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;
}
like image 65
epatel Avatar answered Oct 01 '22 09:10

epatel


If you are using MSVC, you can use

dumpbin /symbols  foo.obj > foo_symbols.txt

To get all of the symbol names (not just functions) into a text file. Then parse the resulting file to extract the function names. Functions will be External symbols in a section that is not UNDEF

Alternatively, you could link your objects into a temporary exe or dll and then look at the .MAP file produced by the linker to get the function names.

Or you could write your own code to parse the .obj files, they are in a modified COFF format and it's not that difficult to locate the symbol table and decode it. I did a partial decode of the COFF format once to get at the symbol table and it took a couple of days to write the code. http://en.wikipedia.org/wiki/COFF

like image 25
John Knoeller Avatar answered Oct 01 '22 09:10

John Knoeller