Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to alias C library functions?

Tags:

c

I have a static C library that I can build with different compile time options (e.g. _BUILD_SMALL, _BUILD_FAST). It has a function

void Foo(void);

I would like to use a single instance of a benchmarking tool to benchmark the "small" and the "fast" versions of the library. I don't want to use .dlls.

How can I link to the "small" and the "fast" libraries and alias the function names so I can call the small version and the fast version. Ideally it would look something like:

void benchmark(void)
{
  FAST_Foo();

  SMALL_Foo();
}

More information:

The library can be built with different optimizations options -Os versus -O3. Also, the algorithms vary slightly (i.e. cached values vs looking up values always). I want to compare the size vs speed tradeoffs of the different versions. I'd like the unit tests and benchmarking to be ran on both versions of the library the easiest way possible.

like image 368
Josh Petitt Avatar asked Aug 15 '12 20:08

Josh Petitt


People also ask

What is an alias in C?

In C, C++, and some other programming languages, the term aliasing refers to a situation where two different expressions or symbols refer to the same object.

How do you assign an alias to a function in Python?

You can define your own alias method by adding the statement a = b to your class definition. This creates an alias method a() for the original method b() .

What is function alias in PEGA?

What is Function Alias in Pega? From OSP dictionary we would define Function alias as the rules that promote the usage of the function (Java/SQL) to the users (non-developers ) who maintain business rules (Decision tree, Decision table, When) or create/configure reports in Production.


2 Answers

This is just a variation of the method as given by @Michał Górny (I run out of comment space there)...

You could create an include file of the following form:

/* Automatically created file - do not edit or ugly dinosaur will eat you */
#ifndef PREFIX
#  define RENAME(f)
#else
#  define RENAME(f) PREFIX ## f
#endif

/* list all the function and variables you want to rename here in one place */
#define func_foo RENAME(func_foo)
#define func_bar RENAME(func_bar)
/* ... many more ... */

#undef RENAME

At least gcc allows you to specify the inclusion of a header file from command line with option -include rename.h (assuming this file is called rename.h). Because you use gcc lookalike options (-O3 and Os), I am assuming you use gcc in the rest of this answer. Otherwise, if your C compiler is reasonable, you should be able to do it in some similar way.

You can create easily two or even three versions of your library that can be linked in at the same time if you want, by providing different options for your C compiler (here through CFLAGS setting):

CFLAGS += -include rename.h -DPREFIX=fast_ -D_BUILD_FAST -O3 -DBENCHMARKING
CFLAGS += -include rename.h -DPREFIX=small_ -D_BUILD_SMALL -Os -DBENCHMARKING
CFLAGS += -D_BUILD_FAST -O2

If your library header files look very regular and if you declare the library private functions static, then it is easy to extract the functions from those header files by some dummy script using very simple regular expressions to automatically generate the rename.h file for you. This is a natural build target if you are using make or something similar. All the global variables also need to be renamed using the same method to allow simultaneous use.

There are three main points with this solution:

  1. The ugly renaming business can be hidden in one file, you do not need to edit the actual source files - especially you do not need to clutter the source files but can keep them clean and easy to read.
  2. The renaming can be easily automated, if you follow some simple principles (coding conventions followed for the header files and the header files will declare all the global variables and functions).
  3. There is no reason to make benchmarking more cumbersome by needing to run your test program multiple times (this is relevant if you are as lazy as I am and dislike repetive tasks as violently as I do - I know many people do not care, it is somewhat a matter of preference).
like image 138
FooF Avatar answered Sep 20 '22 14:09

FooF


One way would be: keep the same name for both and call appropriately depending on the compile time option set.

ifdef SMALL_FOO
void foo() {

/* Small foo code */
}
#endif

ifdef BIG_FOO
void foo() {

/* Big foo code */
}
#endif

Set the SMALL_FOO/BIG_FOO during compilation with -d.

like image 21
P.P Avatar answered Sep 22 '22 14:09

P.P