6

I'm working on some library header file that is supposed to be used from both C and C++. Since C does not have a namespace concept I would add a "library prefix" to all names defined in the header file. By contrast, for C++ I would define a namespace. So I currently think of the design as something like this:

mylib.h

#ifdef __cplusplus
namespace mylib{
#define NAME_PREFIX(identifier) identifier
extern "C" {
#else
#define NAME_PREFIX(identifier) mylib_identifier
#endif

int NAME_PREFIX(foo)(void);

//other declarations go here

#ifdef __cplusplus
} //extern "C"
} //namespace mylib
#endif

I have never seen something like that so I am not sure if that is common. Is it discouraged to do so? What are possible drawbacks?

St.Antario
  • 26,175
  • 41
  • 130
  • 318
  • 4
    How are you going to link object files from C and C++ based on this header if the names don't match? – walnut Oct 17 '19 at 05:36
  • 2
    I've never seen that before either, but I like it--assuming `extern c` still works inside a namespace, of course. –  Oct 17 '19 at 05:36
  • 2
    @Chipster [`extern "C"` does work inside namespaces.](https://stackoverflow.com/questions/28996944/extern-c-linkage-inside-c-namespace) – walnut Oct 17 '19 at 05:39
  • @uneven_mark Agree, that's a problem in general. But is it in case of header-only libraries... ? – St.Antario Oct 17 '19 at 05:40
  • 3
    @St.Antario If there is no external linkage between languages for the library, you don't need `extern "C"`. – walnut Oct 17 '19 at 05:41
  • @uneven_mark So yes, it introduces much more problems than solves... – St.Antario Oct 17 '19 at 05:43
  • 1
    I think it is already a bad idea because the unprefixed `extern "C"` name will pollute the global (C) namespace. – walnut Oct 17 '19 at 05:48

1 Answers1

4

So, as I mentioned in the comments, there are three problems I see with this approach.

First, it does not allow the library to be used with mixed C/C++ translation if any entities are supposed to share linkage between the two languages. If the header file is included in a C translation unit and a C++ translation unit, all declared entities will have different names, either with a prefix or without one. So in effect it will work out as if these were two separate libraries, one used in the C translation unit and one in the C++ translation unit. If any library entities are supposed to share linkage between the translation units, it won't work.

Second, extern "C" inside the namespace will scope the name properly inside the namespace for C++ code. However, in order to guarantee C linkage, the name without namespace prefix must be introduced into the global C namespace, cluttering it with lots of names without a library prefix.

Third, it makes it difficult to write user code that should be translatable between C and C++ as well. Any such user would have to introduce a similar macro.

If the library is not supposed to be used in mixed C/C++ code (or without any shared linkage), then extern "C" is unnecessary and after removing it, I think the approach may be fine.

walnut
  • 21,629
  • 4
  • 23
  • 59