Как связать приложение со статической библиотекой + почему это не работает - PullRequest
0 голосов
/ 29 марта 2010

У меня проблема. Я написал пример кода, и я хочу построить его без ошибки:

main.cpp(.text+0x5): undefined reference to `test()'

Библиотека


test1.c

#include <stdlib.h>
void test()
{
 puts("Działa");
}

test1.h

#ifndef TEST1_H
#define TEST1_H

extern void test();

#endif

Makefile

all:
 gcc -c ./src/test1.c -o ./lib/test1.o
 ar rcs ./lib/libtest1.a ./lib/test1.o

Программа


main.cpp

#include <test1.h>

int main()
{
 test();
 return 0;
}

Makefile

all:
 g++ -static -I../test1/include -L../test1/lib ./src/main.cpp -o ./build/MyApp -ltest1

Что я делаю не так?

Ответы [ 2 ]

10 голосов
/ 29 марта 2010

Вы компилируете функцию кода на C, но ожидаете связать функцию C ++.

Из-за 'type safe linkage' предоставляемая вами функция не является той функцией, которую вызывает код C ++.

Либо в test1.h использовать:

#ifdef __cplusplus
extern "C" {
#endif

extern void test1(void);

#ifdef __cplusplus
}
#endif

Или:

  • Скомпилируйте функцию с помощью компилятора C ++.

Компилятор C ++ будет манипулировать именами символов, чтобы обеспечить безопасную для типов связь (термин, который вы должны быть в состоянии искать через предпочитаемую вами поисковую систему).

'Компилятор' - фактически компоновщик - ищет функцию с искаженным именем C ++, представляющую функцию C ++ с подписью 'void test1 (void);'.

Например (но помните - разные компиляторы преднамеренно манипулируют вещами по-разному), G ++ 4.2.1 на MacOS X 10.6.2 генерирует символ '__Z5test1v' для функции; GCC генерирует символ '_test1'. Ясно, что когда компоновщик ищет «__Z5test1v», символ «_test1» не будет использоваться - он не пишется одинаково. Это хорошая вещь.

Вы можете использовать 'nm -g' в объектном файле для основной программы, чтобы увидеть, что она ищет, и в объектном файле в библиотеке, чтобы увидеть, что она предоставляет. И, учитывая, что написание отличается, поэтому загрузчик не выбирает библиотечную функцию - он ищет что-то с другим именем.

3 голосов
/ 29 марта 2010

Вы вызываете функцию C из функции C ++. Имена между этими двумя именами разные (C ++ изменяет имена для включения информации о параметрах).

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

#ifdef __cplusplus
extern "C" {
#endif

extern void test();

#ifdef __cplusplus
}
#endif

Это сообщит компилятору, что функция следует соглашению об именовании / вызове C.

...