Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Default linkage model in gcc 4.4 vs. gcc >4.4

I'm trying to use two large, complex linear algebra libraries which define many of the same functions. I can't rewrite (legally in one case, but technically in both) either of them. Let's call them "special" and "normal" because I only call a couple functions from special. To consistently call functions defined in normal.h and only in some cases from special.h, I've done something like this:

namespace special_space
{
#include "special.h"  // Defines foo()
}

#include "normal.h"   // Defines foo()

int main() {
  foo();                // Calls foo() defined in normal.h
  special_space::foo(); // Calls foo() defined in special.h
}

With g++-4.4, which was the default where I was developing this, the code compiles and links without warnings, and it executes as I would expect and as I want. This seems to be consistent across platforms, various Linux, Unix and BSD environments. But! if I compile with g++ >4.4, I get warnings about multiple foo() definitions:

In file special.h::line:col: warning: declaration of ‘void special_space::foo()’ with C language linkage [enabled by default]

The resulting executable then segfaults at the call to special_space::foo(). I /think/ that specifying extern "C++" in the definitions found in special.h might fix this, but I'm not allowed to change special.h. So what should I do? More specifically:

1) Is it safe to use g++-4.4? If so -- what changed in subsequent versions and why?

2) If specifying the C++ linkage model really would fix this, is there a way to tell ld to use it by default?

3) If neither of those -- is there another way to call functions from libraries that define functions of the same name?

like image 306
gerowam Avatar asked Nov 10 '22 09:11

gerowam


1 Answers

So as I posted in a comment, wrap the headers includes with

#ifdef __cplusplus
extern "C" {
#endif

#include normal.h

#ifdef __cplusplus
}
#endif

Do this with both headers.

Basically, since you're linking c libraries from c++, which does name mangling (this is what allowes overloading), your calls to the symbols in your c lib were being mangled by the linker. The #ifdef __cplusplus tells the linker not to mangle the names for those specific function symbols.

Ideally, the creators of the library should include this in their headers but you mentioned that you have no control over that. I had a similar problem with some generated code. I had to wrap all my header includes of the generated code in this to allow C++ to call it.

What I don't know, is how it ever worked without this. I've definitely had to do this going back to gcc < 4.4.

like image 179
rost0031 Avatar answered Nov 15 '22 06:11

rost0031