2016-05-26 4 views
2

у меня есть две версии аа общей библиотеки: библиотека версия 2:ссылок на разные версии разделяемых библиотек

simple.h

#pragma once 
int first(int x); 

simple.c

#include "simple.h" 
#include <stdio.h> 

__asm__(".symver first_1_0,[email protected]_1.0"); 
int first_1_0(int x) 
{ 
    printf("lib: %s\n", __FUNCTION__); 
    return x + 1; 
} 

__asm__(".symver first_2_0,[email protected]@LIBSIMPLE_2.0"); 
int first_2_0(int x) 
{ 
    int y; 
    printf("lib: %d\n", y); 
    printf("lib: %s\n", __FUNCTION__); 
    return (x + 1) * 1000; 
} 

компоновщик версия файл сценария:

LIBSIMPLE_1.0{ 
    global: 
    first; 
    local: 
    *; 
}; 

LIBSIMPLE_2.0{ 
    global: 
    first; 
    local: 
    *; 
}; 

gcc -Wall -g -O0 -fPIC -c simple.c 
gcc -shared simple.o -Wl,--version-script,script -o libsimple.so.2.0.0 

И библиотека версия 3:

simple.h

#pragma once 
#ifdef SIMPLELIB_VERSION_3_0 
int first(int x, int normfactor); 
#else 
int first(int x); 
#endif //SIMPLELIB_VERSION_3_0 

simple.c

#include "simple.h" 
#include <stdio.h> 

__asm__(".symver first_1_0,[email protected]_1.0"); 
int first_1_0(int x) 
{ 
    printf("lib: %s\n", __FUNCTION__); 
    return x + 1; 
} 

__asm__(".symver first_2_0,[email protected]_2.0"); 
int first_2_0(int x) 
{ 
    printf("lib: %s\n", __FUNCTION__); 
    return (x + 1) * 1000; 
} 

__asm__(".symver first_3_0,[email protected]@LIBSIMPLE_3.0"); 
int first_3_0(int x, int normfactor) 
{ 
    printf("lib: %s\n", __FUNCTION__); 
    return (x + 1) * normfactor; 
} 

Linker версия файла сценария:

LIBSIMPLE_1.0{ 
    global: 
    first; second; 
    local: 
    *; 
}; 

LIBSIMPLE_2.0{ 
    global: 
    first; 
    local: 
    *; 
}; 

LIBSIMPLE_3.0{ 
    global: 
    first; 
    local: 
    *; 
}; 

gcc -Wall -g -O0 -fPIC -c simple.c 
gcc -shared simple.o -Wl,--version-script,script -o libsimple.so.3.0.0 

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

main.C

#include <stdio.h> 
#include "simple.h" 

int main(int argc, char* argv[]) 
{ 
    int nFirst = first(1, 10); 
    printf("First(1) = %d\n", nFirst); 
} 

Я компилировать приложение со следующими командами:

gcc -g -Wall -DSIMPLELIB_VERSION_3_0 -c main.c 

а потом, случайно, вместо ссылки на библиотеки версии 3, я связанное с библиотекой версии 2. Я ожидал, что ссылки на неудачу, но он прошел, и приложение работает.

gcc main.o -Wl,-L. -lsimple.2.0.0 -Wl,-R. -o demo 

Так что мои вопросы:

  1. Является ли это потому, что экспорт библиотеки символ с именем «функции», и приложение пытается установить связь с тем же именем символа, и поэтому компоновщик не жалуется , и просто связаны с библиотекой версии 2?
  2. Я думал, что C++ управляет именами символов, такого не произойдет, и компоновщик не будет ссылаться на библиотечную версию 2. Так что я все же пробовал, но вместо gcc-компилятора я пытался использовать g ++. Все прошло хорошо, пока я не попытался связать приложение с библиотекой, и я получил ошибку неразрешенных ссылок. Не могу понять, почему.

p.s. Извините за большой объем кода. Я пытался прояснить ситуацию. Благодаря

+0

Im закрытие этот вопрос. Первая часть этого я понимаю, а для второй части я создам новый более конкретный вопрос –

ответ

2

Это потому, что экспорт библиотеки символ с именем «функция», и приложение пытается установить связь с тем же именем символа, и поэтому компоновщик не жаловался, а просто связаны с библиотекой версии 2?

Да, поскольку простая C не имеет функции перегрузки, нет необходимости в mangling, и, как следствие, в качестве символа для связывания будет использоваться только имя функции.В конце вашего код приложения хочет связать с function и ваш код экспорта function, и этого достаточно, чтобы поддерживать компоновщик счастливым (хотя это недействительно с точки зрения двоичного интерфейса).

Я думал, так как с ++ искалечил символьные имена, такие, что бы не случилось, и компоновщик не будет ссылаться на версию библиотеки 2. Таким образом, я попытался все же, но вместо GCC компилятор, я пытался используйте g ++. Все прошло хорошо, пока я не попытался связать приложение с библиотекой, и я получил ошибку неразрешенных ссылок. Не могу понять, почему.

Да, эта проблема не должна возникать в C++ из-за изменения имени. Однако это верно только в том случае, если у вас есть код приложения и код библиотеки в C++ или если вы правильно сориентируете свой код на C и C++.

Трудно сказать (без полного списка), что произошло в вашем случае, когда вы использовали г ++, но от взглядов его вы закончили тем, что код приложения в C++ и код библиотеки еще в C. Если это ваш код приложения теперь захочет связаться с mangled function, а ваш код все еще экспортирует unmangled function.

Чтобы проверить это, вы можете проверить свой объектный файл с чем-то вроде:

nm main.o 

... и посмотреть, какой именно символ она хочет. Если вы получите что-то вроде этого:

... 
    U _Z3functionii 
... 

... вместо:

... 
    U function 
... 

... то, что это так.

Чтобы «исправить» это и сделать свой C++ приложение кода связь с unmangled function из кода библиотеки вам нужно объявить прототип функции, как extern "C".

Смежные вопросы