简体   繁体   中英

Why use an extern “C” around a C++ namespace

A few days back, I came across this piece of C++ code, though I can't paste the code itself, I could recreate the problem with some sample code. First, the file, namespace.h:

#include <iostream>
using namespace std;

namespace useless{
  class X {
     int m_myint;
     static X *m_foobar;
     X* getPrivVal(void);
  public:
     int getMember(void);
     X* getStaticVal(void);
  };
}

Next, namespace.cpp :

#include "namespace.h"

extern "C"{
   namespace useless{
     X* X::m_foobar = NULL;
     X* X::getPrivVal(void){
         if(m_foobar == NULL)
             m_foobar = new X;
         return(m_foobar);
     }
   }
}

namespace useless {
   int X::getMember(void){
       if(m_myint == 0)
           m_myint = 1;
      return(m_myint);
   }
   X* X::getStaticVal(void){
        return(getPrivVal());
   }
}

using namespace useless;

int main(void){
    X y;
    cout << "The int value is " << y.getMember() << endl;
    cout << "The value of the static member is " << y.getStaticVal() << endl;
    return(0);
}

This code compiled and linked fine when I used g++ 3.4.3, but gives the following error when I use g++ 4.x, I have tried with GCC 4.6.1 as well GCC 4.2.1. Have tried it on Linux as well as Mac, same results.

This is the error(Suse):

g++ -o namespace namespace.cpp
namespace.h:8:15: error: previous declaration of useless::X* 
    useless::X::m_foobar with C++ linkage
namespace.cpp:5:11: error: conflicts with new declaration with C linkage

Can someone please shed some light on what the legacy C++ code was looking to do, could this have been a hack or workaround to get around an old problem that I am not aware of any longer. Ohh by the way, the method inside the extern "C" is called by C++ code and not any C code as I initially suspected. FYI, this is legacy code now, may have been written in 2001/2002 period.


Thanks guys. I have gone ahead and got rid of the extern "C" with no major impact. @Bjorn Pollex : The guy who wrote that code is long gone.

The extern "C" directive has two effects, it disables mangling when possible and uses the C calling convention. In this particular case, because there is a namespace in between, name mangling cannot be disabled, so it could have been added to force a particular calling convention.

The code is actually wrong in that the declaration does not force extern "C" but the definition does, which is incorrect. Consider that if the compiler just followed the directive as shown, the caller would use C++ naming and calling conventions, while the function would be using the C variant, if the two differ the result will be undefined behavior.

Seems like an attempt to generate the variables witout C++ name mangling. That's one part of using extern "C" .

The newer compiler obviously realizes that it really doesn't work.

If you have a piece of C++ code that you want to call from a module written in another language (C, FORTRAN or whatever), you want to turn off C++ name mangling.

Edit: The really weird thing is that they did it on the definition but not on the declaration. It's a wonder that it ever compiled

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM