2013-07-23 3 views
0

Я работаю над большим проектом, и случилось так, что в двух местах есть функции, которые принимают одни и те же аргументы и имеют одно и то же имя, хотя они делают другое. Мне посоветовали использовать подход фасада и разместить все в статических библиотеках. Однако это сделало программу чрезвычайно странной. Функции не отделены друг от друга, несмотря на то, что обертки представляют собой отдельные статические библиотеки и имеют отдельные пространства имен. Всегда функция из A.lib называется также также оболочкой B :: BF().C++ Static linking weird behavior

исполняемым:

#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; 
} 

структура файла выглядит следующим образом:

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++ 

И выше была простая программа, вызывающая те. Подробные файлы листинга:

Библиотека --------------:

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); 
    } 
} 

библиотека Б --------------: 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); 
    } 
} 
+0

Возможно взять взгляд на скомпилирована статическая библиотека B? Удостоверьтесь, что он вызывает правильную функцию? Хотя возможно, что компоновщик заменяет его, когда он ссылается в статической библиотеке «А». –

+0

Хорошо ... он отлично работает, когда нет связанного с lib. – Misery

+3

Вы не можете иметь две глобальные функции, имеющие одно и то же имя, в одном статически связанном двоичном файле. Никакой объем упаковки не поможет. Переименуйте один. –

ответ

3

Нет, вы не можете решить эту проблему. Если у вас есть «свободная функция», которая не находится в пространстве имен или в классе [и не указана], она будет иметь то же имя (в C++, если она имеет одинаковые аргументы/тип возврата), поэтому независимо от того, сделайте позже, компоновщик по-прежнему будет ссылаться на первую версию найденной функции.

Есть два очевидных решения:

  1. Rename (один из) функции (s), так что они больше не имеют такое же имя.
  2. Оберните самую основную функцию (ы) в пространство имен и/или класс, чтобы получить квалифицированное имя.

Любое из этих решений включает в себя модификацию FA.c и/или FB.c.

Альтернативой может быть использование общей библиотеки для каждой группы функций - таких, что FA.c и FB.c никогда не находятся в одной и той же общей библиотеке и статически связывают FA.o с одной общей библиотекой и FB. o в другую общую библиотеку. Но это будет означать разделение библиотек, и я ожидаю, что вы решите не делать этого в первую очередь при выборе статической привязки.

Если код compileable (то есть, он не использует new, delete, this или другие ключевые слова C++ в качестве имен переменных, и не идут слишком дикий в проходящих указатели от одного типа к другому без слепков и т.д.) в C++, вы также можете сделать что-то вроде этого:

FA.cpp:

namespace A 
{ 
    #include "FA.c" 
} 

FB.cpp:

namespace B 
{ 
    #include "FB.c" 
} 
+0

Если это был код C++, проблем не было бы, но C не поддерживает пространства имен. Как я могу обойти это? Любой трюк? И переименование функции, которая находится в тысячах других файлов, кажется довольно жуткой:] – Misery

+2

@Misery: Используя интеллектуальную среду IDE, такой рефакторинг должен быть относительно прост. Кроме того, у вас, вероятно, есть множество модульных тестов, которые показывают, что ваш рефакторинг прошел хорошо;) – arne

+0

См. Мое редактирование, вы можете перенести эту функцию в среду C++ с простым включением. Но есть ограничения на это, так как некоторые C-коды не компилируются в компиляторе C++. В противном случае решение arne - ваш лучший вариант. Или некоторые неприятные макросы ...;) –