0
  1. I saw in a C++ program that dlfcn library is used for dynamically linking to a shared object library chosen by the user of the C++ program during runtime, and for calling functions in the chosen shared object library via dlsym() and other functions in dlfcn.

    • Assume the user chooses a shared object library called x.so during runtime. x.so was compiled from a cpp file with definitions of functions enclosed within extern "C". A comment in the cpp file says that the usage of extern "C" is important but without further explanation, and I wonder why?

    • Is it correct that there is only C++ code and no C code involved here? So is extern "C" not necessarily only used when mixing C and C++ code together?

    • Does whether dlfcn library is statically or dynamically linked to the C++ program matters to the questions above?

  2. Now compare to a simpler case, where the shared object library is known much earlier than runtime, and the author of the C++ program specifies it in the C++ program without using dlfcn before compiling it, and then dynamically links the shared object library and the C++ program during runtime. In this case, is `extern "C" still necessary in the cpp file which was compiled into the shared object library?

Thanks.

Tim
  • 1
  • 141
  • 372
  • 590
  • It's kind of implied. Posix is a C specification, so any reference to function pointers in Posix APIs implicitly expect those to be pointers to functions with C language linkage. But the term "C language linkage" is a C++ term; from C's perspective, there are no other kinds of functions. The upshot is that when you use a C API from C++, you can only use functions with C language linkage. – Kerrek SB Jun 21 '16 at 12:05
  • To put it simple, if you have `int foo(int** x, struct Bar*& y)` in your shared library, `extern "C"` allows you to use `dlsym(libhandle, "foo")` instead of `dlsym(libhandle, "_Z3fooPPiRP3Bar")` or whatever mangling of `foo` happens to be in effect this week on your platform. No actual C code need be involved. – n. m. could be an AI Jun 21 '16 at 12:16

1 Answers1

3

extern "C" changes the linkage, and affects name mangling. See What is name mangling, and how does it work?

Without it, exported names in the compiled object will normally be mangled. That means that they cannot be used from C. It also means that looking them up via dlsym() requires using the mangled name.

Is it correct that there is only C++ code and no C code involved here? So is extern "C" not necessarily used when mixing C and C++ code together?

It is not clear what you mean here. If you are compiling C++, then only C++ code is involved at this stage. If you are then linking in any way with a module written in C, then C is involved. If you need an external C library or program to link to your C++-defined functions, then they need to be declared extern "C".

Does whether dlfcn library is statically or dynamically linked to the C++ program matters to the questions above?

No (perhaps you should have explained why you think it might matter).

Now compare to a simpler case, where the shared object library is known much earlier than runtime, and the author of the C++ program specifies it in the C++ program without using dlfcn before compiling it, and then dynamically links the shared object library and the C++ program during runtime. In this case, is `extern "C" still necessary in the cpp file which was compiled into the shared object library?

It is necessary that the declared linkage of the symbols is consistent in the two C++ modules. Certainly, you could remove extern "C" if the modules are both C++. But if one module declares the symbol as extern "C" then the other must also.

Community
  • 1
  • 1
davmac
  • 20,150
  • 1
  • 40
  • 68
  • Thanks. Is it correct that there is only C++ code and no C code involved here? So is extern "C" not necessarily **only** used when mixing C and C++ code together? – Tim Jun 21 '16 at 12:00
  • @Tim the purpose of using `extern "C"` is generally for linking your code with code written in C (or sometimes another language that can use C symbols). Of course there's nothing _preventing_ you from using it if that's not going to be the case. It makes using `dlsym` easier (as per update). – davmac Jun 21 '16 at 12:04
  • the main program is written in C++, and it calls `dlfcn` library to call functions in a shared object library `x.so` which is determined at runtime. The main program, `dlfcn` library and `x.so` are all in the machine language now after compilation. So there seems no C code involved, and no mixing C and C++ code. Is it correct that it doesn't matter that `dlfcn` library was compiled from C files, and `x.so` and the main program were compiled from cpp files, because they are now all in machine language? – Tim Jun 21 '16 at 12:06
  • By "`dlfcn` library" you mean the library providing `dlopen`/`dlsym` etc? No, that won't matter, most likely (that's normally the system C library; it won't link to any of your program's symbols). But the `x.so` library - does it try to resolve symbols from your C++ program? Then they probably need to be unmangled, hence `extern "C"`. – davmac Jun 21 '16 at 12:09
  • I just realized the main c++ program also is in machine language now as an executable, so does it matter the main program was in C++ before compilation? – Tim Jun 21 '16 at 12:11
  • @Tim what matters is if the symbol name in one object matches the symbol name in another. If the name is mangled in one, it must be mangled in the other. If it's not mangled in one, then it must not be mangled in the other. Everything else you mention is unimportant. – davmac Jun 21 '16 at 12:14
  • Before and after mangling by a C++ compiler, do two symbols with the same name in different object files, still have the same mangled name? – Tim Jun 21 '16 at 12:29
  • @Tim yes (bearing in mind that "name" refers to the fully-qualified name including signature), or how would they link? See the link on name mangling I posted at the top of my answer - read it! – davmac Jun 21 '16 at 13:01