Alex Rivera | Logout

Preferred method to use two names to call the same function in C

Asked 2012-04-02T20:52:20.660
20

I know there are at least three popular methods to call the same function with multiple names. I haven't actually heard of someone using the fourth method for this purpose.

1). Could use #defines:

int my_function (int);


#define my_func my_function

OR

#define my_func(int (a)) my_function(int (a))

2). Embedded function calls are another possibility:

int my_func(int a) {
    return my_function(a);
}

3). Use a weak alias in the linker:

int my_func(int a) __attribute__((weak, alias("my_function")));

4). Function pointers:

int (* const my_func)(int) = my_function;

The reason I need multiple names is for a mathematical library that has multiple implementations of the same method.

For example, I need an efficient method to calculate the square root of a scalar floating point number. So I could just use math.h's sqrt(). This is not very efficient. So I write one or two other methods, such as one using Newton's Method. The problem is each technique is better on certain processors (in my case microcontrollers). So I want the compilation process to choose the best method.

I think this means it would be best to use either the macros or the weak alias since those techniques could easily be grouped in a few #ifdef statements in the header files. This simplifies maintenance (relatively). It is also possible to do using the function pointers, but it would have to be in the source file with extern declarations of the general functions in the header file.

Which do you think is the better method?


Edit:

From the proposed solutions, there appears to be two important questions that I did not address.

Q. Are the users working primarily in C/C++?

Edit
Report

3 Answers

7

Depending on the intended audience for your library, I suggest you chose between 2 alternatives:

  1. If the consumer of your library is guaranteed to be Cish, use #define sqrt newton_sqrt for optimal readability

  2. If some consumers of your library are not of the C variety (think bindings to Dephi, .NET, whatever) try to avoid consumer-visible #defines. This is a major PITA for bindings, as macros are not visible on the binary - embedded function calls are the most binding-friendly.

answered 2012-04-02T21:00:55.010
5

What you can do is this. In header file (.h):

 int function(void);

In the source file (.c):

static int function_implementation_a(void);
static int function_implementation_b(void);
static int function_implementation_c(void);

#if ARCH == ARCH_A
int function(void)
{
    return function_implementation_a(); 
}
#elif ARCH == ARCH_B
int function(void)
{
    return function_implementation_b();
}
#else
int function(void)
{
    return function_implementation_c();
}
#endif // ARCH

Static functions called once are often inlined by the implementation. This is the case for example with gcc by default : -finline-functions-called-once is enabled even in -O0. The static functions that are not called are also usually not included in the final binary.

Note that I don't put the #if and #else in a single function body because I find the code more readable when #if directives are outside the functions body.

Note this way works better with embedded code where libraries are usually distributed in their source form.

answered 2012-04-02T21:15:32.187
0

You might you create a test suite for all algorithms and run it on the target to determine which are the best performing, then have the test suite automatically generate the necessary linker aliases (method 3).

Beyond that a simple #define (method 1) probably the simplest, and will not and any potential overhead. It does however expose to the library user that there might be multiple implementations, which may be undesirable.

Personally, since only one implementation of each function is likley to be optimal on any specific target, I'd use the test suite to determine the required versions for each target and build a separate library for each target with only those one version of each function the correct function name directly.

answered 2012-04-02T22:28:16.967

Your Answer