2009-03-25 9 views
4

дубликата вопроса: C function conflictКак использовать 2 C LIBS, которые экспортируют те же функции имена


Привет, в моем текущем проекте я должен использовать какое-то интерфейс Lib. Названия функций задаются этим интерфейсом, что делают эти функции, это выбор разработчиков. Насколько я могу судить, проект должен использовать эти функции, и когда дело доходит до компиляции, вы выбираете lib и вместе с ним функциональность. То, что я пытаюсь сделать, это использовать существующий LIB и мой LIB в то же время, окружив другой и вызвать его в мейна функции:

otherlib:

int function1 (int a) { 
// do something 
} 

MyLib:

int function1 (int a) { 
//my code here 
    otherlib::function1(a); 
} 

Проблема в том, что у меня нет доступа к другой lib, а другая lib не имеет пространств имен. Я уже пробовал

namespace old { 
    #include "otherlib.h" 
} 

а затем вызывать старую функцию старым :: function1 в моей функции. Это работает до тех пор, пока это только заголовочный файл. Lib экспортирует символ в глобальное пространство. Также что-то вроде

namespace new { 
    function1 (int a) { 
     ::function1(a); 
    } 
} 

не работал. И последнее, но не менее важное: я попытался использовать ifdefs и определил here

но я не был успешным.

Любые идеи, как это решить? Заранее спасибо.

EDIT:. Я ни есть доступ к старому Lib, ни проекта оба ЛИЭС должны быть использованы в

EDIT2: по крайней мере, старый Lib статический один

+0

Я видел это, но у меня нет доступа к проекту, в котором они будут использоваться. – DaClown

ответ

6

Пространства имен в C решена с использованием имен библиотек префиксы, как:

libfoo -> foo_function1
libbar -> bar_function1

Эти префиксы являются фактическими пространствами имен. поэтому, если вы пишете libbar

int bar_function1(int a) { 
    function1(a); 
} 

Это способ решения проблем.

C имеет пространство имен --- они просто называют префиксов;)

Другим вариантом является, чтобы сделать различные пакости с динамической загрузкой библиотек, таких как:

h1=dlopen("libfoo.so") 
foo_function1=dlsym(h1,"function1") 

h2=dlopen("libbar.so") 
bar_function1=dlsym(h2,"function1") 
+0

Спасибо за ваш ответ. К сожалению, у меня нет доступа к старой библиотеке или к проекту, в котором она будет использоваться. И по крайней мере старая библиотека статична. – DaClown

3

Кажется, как будто другой Lib является C, а ваш код - C++. Вы можете столкнуться с проблемой перекоса (компиляторы C++ меняют символы - добавьте лишние вещи в имя символа, чтобы дифференцировать перегрузки и т. П.).

Если библиотека чистый C, вы можете попробовать:

extern "C" { // disable mangling of symbol names in the block 
#include "otherlib.h" 
} 

namespace new_lib { // new is a reserved word 
    int function1(int a) { 
     ::function1(a); 
    } 
} 

я не пробовал. Также рассмотрите возможность предоставления сообщений об ошибках, которые вы получаете.

Другим вариантом будет (если библиотека динамична) динамически загружать библиотеку и вызывать функцию. В Linux (я не знаю об окнах), вы можете использовать dlopen, чтобы открыть библиотеку, dlsym для получения символа и назовите его:

// off the top of my head, not tried: 
int function1(int a) 
{ 
    int (*f)(int); // define the function pointer 
    void * handle = dlopen("library.so"); 
    f = dlsym(handle, "function1"); 
    f(a); // calls function1(a) in the dynamic library 
} 

В этом случае, как вы не связи с библиотекой вы выиграли 't получить конфликт символов, но опять же, он действителен только для динамических библиотек, и это довольно громоздко для обычного использования.

UPDATE

Если ваши пользователи не будут использовать «otherlib» непосредственно (они не будут включать в свои заголовки), и они будут только C++, то первый подход может быть возможным (даже если ужасно читать):

// newlib.h 
namespace hideout { 
    int f(int a); 
} 
using namespace hideout; // usually I would not put this on the header 

// newlib.cpp 
extern "C" { // if otherlib is C, else remove this line 
#include "otherlib.h" 
} 
namespace hideout { 
    int f(int a) { return ::f(a*2); } 
} 

// main.cpp 
#include "newlib.h" 
int main() 
{ 
    std::cout << f(5) << std::endl; 
} 

Как это работает? Пользовательский код будет видеть только объявление функции1 (в примере f()), поскольку они не включают otherlib.h. Внутри блока компиляции вы видите два объявления, но вы различаете их с помощью пространства имен. Оператор using в заголовке не беспокоит вас, так как вы полностью откликнулись на свой cpp. Пользователь main.cpp будет включать только ваш заголовок, поэтому компилятор увидит только hideout :: f и увидит его в любом месте из-за инструкции using. Компоновщик не будет иметь никаких проблем, как символ C++ является искаженной идентификацией реального пространства имен:

// g++ 4.0 in macosx: 
00002dbe T __ZN7hideout9function1Ei // namespace hideout, function1 takes int, returns int 
00002db0 T _function1 

Если код пользователя будет включать в себя как ваш заголовок и otherlib.h то он должен будет квалифицироваться, какая функцию он хочет вызвать ,

+0

Спасибо за ваш ответ. Ваше первое предложение не работает для меня. У меня нет контроля над именами функций, которые должны были бы изменить область действия, используя «namespace new_lib;», и это помещает new_lib ns в глобальную, где функция уже определена. Я попробую второй путь. – DaClown

1

Именно этот вопрос задавали только вчера, но поисковая система SO лишила всех моих попыток найти его - когда в имени богов они goinmg заменят это поиском, который на самом деле находит вещи ?????

+0

Часть бремени лежит на нас. Нам нужно использовать (и избегать использования) ключевые слова, которые относятся (не относятся) к нашему субъекту. – Les

+0

«Именно этот вопрос задавали только вчера, но поисковая служба SO лишила всех моих попыток найти его» << это правда soo :) Я не люблю SO search facils либо :) –

1

Если вы действительно в отчаянии, вы можете написать библиотеку-оболочку, которая использует пространства имен или префиксы или позволяет использовать dlsym. Эта библиотека обертки должна быть динамически связана (чтобы избежать конфликтов символов). Затем динамическая библиотека могла безопасно использовать старую библиотеку, встроенную в нее. Просто убедитесь, что вы не экспортируете символы из статической библиотеки при создании библиотеки динамической обертки.

1

Вы не можете решить эту проблему во время ссылки, поэтому вам придется ее разрешать во время выполнения через динамические библиотеки. Символ для этих функций, по сути, выпекается после создания библиотеки. Если две библиотеки экспортируют один и тот же символ, они не могут быть связаны со статически.