19

Introduction

Hello folks, I recently learned to program in C! (This was a huge step for me, since C++ was the first language, I had contact with and scared me off for nearly 10 years.) Coming from a mostly OO background (Java + C#), this was a very nice paradigm shift.

I love C. It's such a beautiful language. What surprised me the most, is the high grade of modularity and code reusability C supports - of course it's not as high as in a OO-language, but still far beyond my expectations for an imperative language.

Question

How do I prevent naming conflicts between the client code and my C library code? In Java there are packages, in C# there are namespaces. Imagine I write a C library, which offers the operation "add". It is very likely, that the client already uses an operation called like that - what do I do?

I'm especially looking for a client friendly solution. For example, I wouldn't like to prefix all my api operations like "myuniquelibname_add" at all. What are the common solutions to this in the C world? Do you put all api operations in a struct, so the client can choose its own prefix?

I'm very looking forward to the insights I get through your answers!

EDIT (modified question)

Dear Answerers, thank You for Your answers! I now see, that prefixes are the only way to safely avoid naming conflicts. So, I would like to modifiy my question: What possibilities do I have, to let the client choose his own prefix?

The answer Unwind posted, is one way. It doesn't use prefixes in the normal sense, but one has to prefix every api call by "api->". What further solutions are there (like using a #define for example)?

EDIT 2 (status update)

It all boils down to one of two approaches:

  • Using a struct
  • Using #define (note: There are many ways, how one can use #define to achieve, what I desire)

I will not accept any answer, because I think that there is no correct answer. The solution one chooses rather depends on the particular case and one's own preferences. I, by myself, will try out all the approaches You mentioned to find out which suits me best in which situation. Feel free to post arguments for or against certain appraoches in the comments of the corresponding answers.

Finally, I would like to especially thank:

  • Unwind - for his sophisticated answer including a full implementation of the "struct-method"
  • Christoph - for his good answer and pointing me to Namespaces in C
  • All others - for Your great input

If someone finds it appropriate to close this question (as no further insights to expect), he/she should feel free to do so - I can not decide this, as I'm no C guru.

Community
  • 1
  • 1
Dave O.
  • 2,231
  • 3
  • 21
  • 25

8 Answers8

20

I'm no C guru, but from the libraries I have used, it is quite common to use a prefix to separate functions.

For example, SDL will use SDL, OpenGL will use gl, etc...

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
phtrivier
  • 13,047
  • 6
  • 48
  • 79
  • After having written a pretty big C library recently, and trying to use one of the alternative approaches, I finally went back to a simple prefix. – Dave O. Feb 24 '11 at 23:55
14

The struct way that Ken mentions would look something like this:

struct MyCoolApi
{
  int (*add)(int x, int y);
};

MyCoolApi * my_cool_api_initialize(void);

Then clients would do:

#include <stdio.h>
#include <stdlib.h>

#include "mycoolapi.h"

int main(void)
{
  struct MyCoolApi *api;

  if((api = my_cool_api_initialize()) != NULL)
  {
    int sum = api->add(3, 39);

    printf("The cool API considers 3 + 39 to be %d\n", sum);
  }
  return EXIT_SUCCESS;
}

This still has "namespace-issues"; the struct name (called the "struct tag") needs to be unique, and you can't declare nested structs that are useful by themselves. It works well for collecting functions though, and is a technique you see quite often in C.

UPDATE: Here's how the implementation side could look, this was requested in a comment:

#include "mycoolapi.h"

/* Note: This does **not** pollute the global namespace,
 * since the function is static.
*/
static int add(int x, int y)
{
  return x + y;
}

struct MyCoolApi * my_cool_api_initialize(void)
{
  /* Since we don't need to do anything at initialize,
   * just keep a const struct ready and return it.
  */
  static const struct MyCoolApi the_api = {
    add
  };

  return &the_api;
}
unwind
  • 391,730
  • 64
  • 469
  • 606
  • @unwind: Thx for the insight. I see the additional work involved with this solution and its limits. Though the nice thing is, that the client can choose his own "prefix"("api" in your example). 2 questions: Could you provide the implementation for "my_cool_api_initialize"? Are there other ways to let the client choose his own prefix (using #define)? – Dave O. Jan 03 '10 at 03:08
  • Why initialize the api structure at runtime? Just use an initializer in `my_cool_api_initialize()`, and while at it, make the structure `const` so compilers with link-time optimizations can inline the function pointers; you might even want to define the function in a `.h` file to make this possible even for compilers without link-time optimizations... – Christoph Jan 03 '10 at 11:30
  • @Christoph: I was being a bit general-purpose; perhaps the API would need to do something at run-time. I chopped it out, now the implementation is more minimal. – unwind Jan 03 '10 at 12:14
  • @unwind: Thank You for the effort. – Dave O. Jan 03 '10 at 12:40
  • Why the declaration of add function use void: `void (*add)(int x, int y);` different of its implementation `static int add(int x, int y)` that use int? @unwind – Simon Puente Sep 02 '15 at 20:04
7

It's a shame you got scared off by C++, as it has namespaces to deal with precisely this problem. In C, you are pretty much limited to using prefixes - you certainly can't "put api operations in a struct".

Edit: In response to your second question regarding allowing users to specify their own prefix, I would avoid it like the plague. 99.9% of users will be happy with whatever prefix you provide (assuming it isn't too silly) and will be very UNHAPPY at the hoops (macros, structs, whatever) they will have to jump through to satisfy the remaining 0.1%.

  • 4
    Why so down on using a struct as a namespace? Just make a struct of function pointers and it looks very similar to static class methods. This defeats a bunch of optimizations, but also gives you more control and opens up interesting state management options. – Ken Fox Jan 01 '10 at 15:52
  • About all of them in Windows. COM interfaces. – Hans Passant Jan 01 '10 at 16:03
  • I must admit I thought the OP was asking about "plain old" C libraries like SQLite or ncurses. Also, I do a fair bit of Windows programming, but never use COM, so I guess not "about all of them." –  Jan 01 '10 at 16:12
  • @Neil: Thx for editing Your answer. I appreciate Your opinion – Dave O. Jan 03 '10 at 17:36
  • @Ken Fox: Could You elaborate on "state management options"? Thx in advance. – Dave O. Jan 04 '10 at 01:39
  • 2
    Since you mentioned SQLite, I thought it was appropriate to point out that SQLite _DOES_ do exactly that! http://www.sqlite.org/c3ref/io_methods.html and http://www.sqlite.org/c3ref/vfs.html – Wiz Mar 30 '13 at 00:14
5

As a library user, you can easily define your own shortened namespaces via the preprocessor; the result will look a bit strange, but it works:

#define ns(NAME) my_cool_namespace_ ## NAME

makes it possible to write

ns(foo)(42)

instead of

my_cool_namespace_foo(42)

As a library author, you can provide shortened names as desribed here.

If you follow unwinds's advice and create an API structure, you should make the function pointers compile-time constants to make inlinig possible, ie in your .h file, use the follwoing code:

// canonical name
extern int my_cool_api_add(int x, int y);

// API structure
struct my_cool_api
{
    int (*add)(int x, int y);
};

typedef const struct my_cool_api *MyCoolApi;

// define in header to make inlining possible
static MyCoolApi my_cool_api_initialize(void)
{
    static const struct my_cool_api the_api = { my_cool_api_add };
    return &the_api;
}
Community
  • 1
  • 1
Christoph
  • 164,997
  • 36
  • 182
  • 240
3

Unfortunately, there's no sure way to avoid name clashes in C. Since it lacks namespaces, you're left with prefixing the names of global functions and variables. Most libraries pick some short and "unique" prefix (unique is in quotes for obvious reasons), and hope that no clashes occur.

One thing to note is that most of the code of a library can be statically declared - meaning that it won't clash with similarly named functions in other files. But exported functions indeed have to be carefully prefixed.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
1

Since you are exposing functions with the same name client cannot include your library header files along with other header files which have name collision. In this case you add the following in the header file before the function prototype and this wouldn't effect client usage as well.

#define add myuniquelibname_add

Please note this is a quick fix solution and should be the last option.

Andy
  • 1,035
  • 2
  • 9
  • 14
  • Wouldn't I rather prefix all my exposed api operations by a "unique" prefix and then let the client do(for example): #define $ myuniquelibname, so he then could do something like "$_add(...)", instead of "myunique.._add(...)"? Plus: Why do You consider that the last option? – Dave O. Jan 03 '10 at 03:21
  • @Dave: $_add(...) won't work as the identifier is not a C token. I would have the #define in the library header file instead of the client. From the usability aspect client wants add functionality by calling add(), client doesn't want to consider about symbol collision. By including the appropriate header files the add function from the library should be invoked. As we expect the client to use only one header file and ensure that header files from two libraries with name collision are not included. This would invariably lead to some maintenance issues in future. – Andy Jan 03 '10 at 15:55
1

For a really huge example of the struct method, take a look at the Linux kernel; 30-odd million lines of C in that style.

Andrew McGregor
  • 31,730
  • 2
  • 29
  • 28
  • 1
    linux doesn't use that for name collision issues, it uses for reproducing virtual functions and similar. For example the VFS is based on structs with function pointers for the operations which are different for each filesystem type. – Evan Teran Jan 01 '10 at 20:33
0

Prefixes are only choice on C level.

On some platforms (that support separate namespaces for linkers, like Windows, OS X and some commercial unices, but not Linux and FreeBSD) you can workaround conflicts by stuffing code in a library, and only export the symbols from the library you really need. (and e.g. aliasing in the importlib in case there are conflicts in exported symbols)

Marco van de Voort
  • 25,628
  • 5
  • 56
  • 89