Cyan
Cyan

Reputation: 13948

Keep functions private into a lib in C

I recently had to face a fairly complex issue regarding lib management, but I would be very surprised to be the first one.

Let's imagine you are creating a library (static or dynamic) called lib1 in C. Inside lib1 are a few functions that are exposed through an API, and a few other ones which remain private.

Ideally, the private functions would be static. Unfortunately, let's assume one of the source files, called extmod.c, come from another project, and it would be beneficial to keep it unmodified. Therefore, it becomes unpractical to static the functions it defines.

As a consequence, all the functions defined into extmod are present into lib1 ABI, but not the API, since the relevant *.h is not shipped. So no one notice.

Unfortunately, at later stage, someone wants to link both lib1 and another lib2 which also includes extmod. It results in a linking error, due to duplicate definitions.

In C++, the answer to this problem would be a simple namespace. In C, we are less lucky.

There are a few solutions to this problem, but I would like to probe if anyone believes to have found an efficient and non-invasive way. By "non-invasive", I mean a method which avoids if possible to modify extmod.c.

Among the possible workaround, there is the possibility to change all definitions from extmod.c using a different prefix, effectively emulating namespace. Or the possibility to put the content of extmod.c into extmod.h and static everything. Both method do extensively modify extmod though ...

Note that I've looked at this previous answer, but it doesn't address this specific concern.

Upvotes: 1

Views: 792

Answers (3)

user3386109
user3386109

Reputation: 34829

Here's the answer (in the form of a question). The relevant portion:

objcopy --prefix-symbols allows me to prefix all symbols exported by an object file / static library.

Upvotes: 2

harshad shirwadkar
harshad shirwadkar

Reputation: 71

One way you can do prefixing without actually editing extmod.c is as follows:

Create a new header file extmod_prefix.h as:

#ifndef EXTMOD_PREFIX_H
#define EXTMOD_PREFIX_H

#ifdef LIB1
#define PREFIX lib1_
#else
#ifdef LIB2
#define PREFIX lib2_
#endif
#endif

#define function_in_extmod PREFIX##function_in_extmod
/* Do this for all the functions in extmod.c */

#endif

Include this file in extmod.h and define LIB1 in lib1's build process and LIB2 in lib2.

This way, all the functions in extmod.c will be prefixed by lib1_ in lib1 and lib2_ in lib2.

Upvotes: 2

Shawn Rakowski
Shawn Rakowski

Reputation: 5714

You could implement your 'different prefix' solution by excluding extmod.c from your your build and instead treating it as header file in a way. Use the C pre-processor to effectively modify the file without actually modifying it. For example if extmod.c contains:

void print_hello()
{
   printf("hello!");
}

Exclude this file from your build and add one called ns_extmod.c. The content of this file should look like this:

#define print_hello ns_print_hello
#include "extmod.c"

On compilation, print_hello will be renamed to ns_print_hello by the C pre-processor but the original file will remain intact.

Alternatively, IF AND ONLY IF the function are not called internally by extmod.c, it might work to use the preprocessor to make them static in the same way:

#define print_hello static print_hello
#include "extmod.c"

This should work for you assuming you have control over the build process.

Upvotes: 4

Related Questions