Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use an extern "C" around a C++ namespace

Tags:

c++

c

gcc

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.

like image 384
RNS Avatar asked Oct 10 '11 07:10

RNS


People also ask

Why do you need extern C?

Using extern "C" lets the compiler know that we want to use C naming and calling conventions. This causes the compiler to sort of entering C mode inside our C++ code. This is needed because C++ compilers mangle the names in their symbol table differently than C compilers and hence behave differently than C compilers.

Do you need extern C?

You need to use extern "C" in C++ when declaring a function that was implemented/compiled in C. The use of extern "C" tells the compiler/linker to use the C naming and calling conventions, instead of the C++ name mangling and C++ calling conventions that would be used otherwise.

Can a namespace be extern?

C++ static code analysis: 'extern "C"' should not be used with namespaces.

What is the purpose of namespace in C?

Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries.


2 Answers

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.

like image 87
David Rodríguez - dribeas Avatar answered Sep 19 '22 10:09

David Rodríguez - dribeas


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.

like image 29
Bo Persson Avatar answered Sep 20 '22 10:09

Bo Persson