Misery
Misery

Reputation: 689

C++ Static linking weird behavior

I am working on a big project, and it happened that in two places there are functions which take the same arguments and have the same name, although they do a different thing. I was adviced to use facade approach and place everything in static libraries. However it made program extremely strange. Functions are not separated from each other, despite the fact that wrappers are separate static libs and have separate name spaces. Always function from A.lib is called- also by B::BF() wrapper.

executable:

#include <iostream>    
#include "A/AWrapper.h"
#include "B/BWrapper.h"

int main()
{
    std::cout<<"A="<<A::AF(2)<<std::endl;
    std::cout<<"B="<<B::BF(2)<<std::endl;   //uses function int F(int x) from A lib

    getchar();
    return 0;
}

File structure is as follows:

Dir A:

FA.h, FA.c  //function int F(int x) is defined - C language
AWrapper.h, AWrapper.cpp //a simple wrapper function AF of int F(int x); C++

Dir B:

FB.h, FB.c  //function int F(int x) is defined - C language
BWrapper.h, BWrapper.cpp //a simple wrapper function AF of int F(int x); C++

And above was the simple program calling those. Detailed files listing:

A library--------------:

FA.h:

#ifndef A_H_INCLUDED
#define A_H_INCLUDED

int F(int x);

#endif // A_H_INCLUDED

FA.c:

#include "FA.h"

int F(int x)
{
   return x*x;
}

AWrapper.h:

#ifndef AWRAPPER_H_INCLUDED
#define AWRAPPER_H_INCLUDED

namespace A{
   int AF(int x);
}

#endif // AWRAPPER_H_INCLUDED

AWrapper.cpp

#include "AWrapper.h"

extern "C"{
#include "FA.h"
}

namespace A{   
    int AF(int x)
    {
       return F(x);
    }
}

B library--------------: FB.h:

#ifndef B_H_INCLUDED
#define B_H_INCLUDED

int F(int x);

#endif // B_H_INCLUDED

FB.c:

#include "FB.h"

#define n 5

int F(int x)
{
   return -x*x*n;
}

BWrapper.h:

#ifndef BWRAPPER_H_INCLUDED
#define BWRAPPER_H_INCLUDED

namespace B{

   int BF(int x);
}

#endif // BWRAPPER_H_INCLUDED

BWrapper.h:

#include "BWrapper.h"

extern "C"{
#include "FB.h"
}

namespace B{

   int BF(int x)
   {
      return F(x);
   }
}

Upvotes: 0

Views: 156

Answers (1)

Mats Petersson
Mats Petersson

Reputation: 129314

No, you can't solve it that way. If you have a "free function" that is not in a namespace or a class [and not inlined], it will have the same name (in C++ if it has the same arguments/return type) - so no matter how much wrapping you do later, the linker will still link against the first version of the function it finds.

There are two obvious solutions:

  1. Rename (one of) the function(s) so that they no longer have the same name.
  2. Wrap the very basic function(s) into a namespace and/or class, so that it gets a qualified name.

Either of these solutions involve modifying the FA.c and/or FB.c.

An alternative would be to use a shared library for each group of functions - such that FA.c and FB.c are never in the same shared library, and statically link FA.o to one shared library, and FB.o to another shared library. But this will mean having shared libraries, and I expect you choose not to do that in the first place when choosing static linking.

If the code is compileable (that is, it doesn't use new, delete, this or other C++ keywords as variable names, and doesn't go too wild in passing pointers from one type to another without casts, etc) in C++, you can also do something like this:

FA.cpp:

namespace A
{
    #include "FA.c"
}

FB.cpp:

namespace B
{
    #include "FB.c"
}

Upvotes: 3

Related Questions