Search code examples
c++xcodec++11externlinkage

C++: Declaration of variable in global scope conflicts with declaration with C language linkage


I have some legacy code of InDesign Plugin that I am trying to compile for new version of InDesign that uses C++11 supported compiler with XCode.

There is a header file AdWrksSession.h that contains a class object with C linkage as following. As declaration of an extern object/variable goes:

extern "C" CAdWrksSession gAdWrksSession;

and the cpp file AdWrksSession.cpp contains a global class object with Default constructor of the same name as the extern object :

CAdWrksSession gAdWrksSession;

The older compilers were not showing any error message for this but when using it with new compiler provided by Apple for XCode 7.2.1 with C++11 support it shows me the following error:

Declaration of 'gAdWrksSession' in global scope conflicts with declaration with C language linkage

I have tried following already asked questions for C linkage:

Compiler error for conflicting variable declarations: "conflicts with new declaration with 'C' linkage"

What is "extern linkage and with C language linkage"

Mixing declarations with extern, static and no storage specifier in global scope

I tried following syntaxes for extern variable declaration in header file:

#ifdef __cplusplus
   extern "C" {
#endif
        CAdWrksSession gAdWrksSession;
#ifdef __cplusplus
    }
#endif

and

#ifdef COMPILE_FOR_C_LINKAGE
     extern "C" CAdWrksSession gAdWrksSession; 
#else
     extern "C++" CAdWrksSession gAdWrksSession;
#endif

but nothing has worked so far.

When I make the header file declaration as static

static CAdWrksSession gAdWrksSession; //Header File

then the code builds successfully but the feature doesn't work, of course.

UPDATE: If I remove C linkage then I get a linker error as following:

Undefined symbols for architecture x86_64:
  "smart::gAdWrksSession", referenced from:
....//Names of generated object files
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 
(use -v to see invocation)`

Can anyone help me here? Thanks.


Solution

  • I think the use of extern "C" you are using in the header is ignored if CAdWrksSession is really a class and not an opaque pointer. There is some discussion in this stack overflow question about the behavior of extern "C".

    The only way to be sure that your header is is really C is to include the header in a dummy main.c and try to link the library with it. (Let me know if you want more clarification on this)

    However maybe we can find another approach in order to solve your issue. I don't know the restrictions you have for this plugin. I would propose that you make a proxy library that is a shared object which links privately (and statically too if possible) with the legacy code. This is, applying the proxy design pattern see API section book 3.4.1 to all the classes you need to expose.

    Then you can make the new code link with this proxy library, this way you will not have name collisions.