开发者

What is the Effect of Declaring 'extern "C"' in the Header to a C++ Shared Library?

Based on this question I understand the purpose of the construct in linking C libraries with C++ code. Now suppose the following:

I have a '.so' shared library compiled with a C++ compiler. The header has a 'typedef stuct' and a number of function declarations. If the header includes the extern "C" declaration...

#ifdef __cplusplus
extern "C"
{
#endif

  // typedef struct ...;
  // function decls

#ifdef __cplusplus
}
#endif

... what is the effect? Specifically I'm wondering开发者_如何转开发 if there are any detrimental side effects of that declaration since the shared library is compiled as C++, not C.

Is there any reason to have the extern "C" declaration in this case?


This is important so that the compiler doesn't name mangle. C++ uses name mangling to differentiate functions with operator overloads.

Run "/usr/bin/nm" against a binary to see what C++ does with your function names: _ZSt8_DestroyIN9__gnu_cxx17__normal_iteratorIPiSt6vectorIiSaIiEEEEiEvT_S7_SaIT0_E

extern "C" prevents that name mangling.

IIRC, that makes it possible for program to dynamically link in symbols at run time. It's common for "plugin" type architectures.


When compiling C++ the method name changes (mangling) - and you won't be able to call that method from another dll/exe that uses C.

In order to keep the class and method name you need to compile them as "C" without name mangling.

The library is still a C++ library but it exposes some of its declarations (the one in the extern "c" block) as C methods.


The #ifdef guarded extern declaration is to tell C linkers that the symbols have C (unmangled) symbol table entries. The #ifdef ensures that there is no effect in the code unit (file) compiled by a C compiler.


One detriment to using extern "C" for a C++ API is that it prevents you from having function overloads:

extern "C"
{
    // ILLEGAL - C linkage does not support function overloading
    void foo(int x);
    void foo(const char *str);
}


The #ifdef in the example means that only a C++ compiler will see the extern wrapping the header file which will mean that it will produce non-mangled names. A C compiler doesn't see the extern (which it wouldn't understand), but always produces non-mangled names.

This means that both C and C++ compilers will produce the same symbols in their object files, so whichever compiler produces object code for the declared functions, all the object files will successfully link because symbols have the same linkage and the same name.

There should be no implications for either statically linking, or linking with a shared library.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜