0

I'd like to make a tool that automatically wraps C libraries in:

#ifdef __cplusplus
extern "C" {
#endif

But I'm confused by what exactly needs to be wrapped with extern "C", and what needn't be. Only functions? What about any (shock-horror) global variables? Anything else?

If I write a script that just finds all functions and wraps them with extern "C", is that enough?

And finally: if the library already wrapped its functions with extern "C" and then they're wrapped again, can I trust that nothing bad happens and it'll still work fine, or do I need to explicitly check for this?

Alasdair
  • 13,348
  • 18
  • 82
  • 138
  • `extern "C"` may not be the only thing you have to worry about. A few constructs are valid in C, but invalid in C++ (e.g. anonymous structs). The C library header files need to be free of such constructs. See also https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B. – nielsen May 01 '21 at 06:24

2 Answers2

5

It does not matter, because anything that does not need it (such as macros and comments) will be unaffected by it, so you can just wrap the entire header content - and that hardly requires a a "tool".

Also not this is not "modifying the library", just modifying the header.

Nested wrapping is benign - applying C linkage to something that already has it has no effect.

What extern "C" does is tell the C++ compiler not to apply name mangling to the specified symbol because it has C linkage and the corresponding name in the library has C linkage and is not name-mangled.

Name-mangling is the means by which C++ applies meta-data to a symbols in order to provide type information and parameter counts in order to support C++ features that require this information such as function overloading.

Clifford
  • 88,407
  • 13
  • 85
  • 165
0

See this answer here which is partially related.

You'll basically just want to either:

  1. Autowrap an include, i.e. extern "C" { #include <foo.h> }

  2. Autowrap the C header files being included by the include (so, at the start of "foo.h" as opposed to the include statement itself)

As far as doubly-wrapped extern "C"s, I tested it with these files:

lib.h:

#pragma once
#ifdef __cplusplus
extern "C" {
#endif
    void printHWorld(void);
#ifdef __cplusplus
}
#endif

lib.c:

#include <stdlio.h>
#include <lib.h>

void printHWorld(void) {
    printf("Hello, world!\n");
}

main.cpp:

#ifdef __cplusplus
extern "C" {
#endif
    #include <lib.h>
#ifdef __cplusplus
}
#endif

int main(void) {
    printHWorld();
    return 0;
}

I then built it with the following commands:

gcc -Wall -O2 -I. -o lib.o -c lib.c

g++ -Wall -O2 -I. -o main.o -c main.cpp

g++ -o test main.o lib.o

And that worked just fine, so I don't think you need to worry about the double extern "C"

Dylan Turner
  • 322
  • 1
  • 12
  • Thanks for your answer! I'm having difficulty understanding the first part of your answer. I just wrap the C filename at the include point in C++ code? So I don't need to modify the C library? And I don't need to wrap functions? Please could you explain more clearly - thanks! – Alasdair May 01 '21 at 06:06
  • @Alasdair According to one of the answers on the other question I linked to, you can just do: `extern "C" { #include "library_file.h" }` – Dylan Turner May 02 '21 at 02:25