如何将应用程序与静态库链接+为什么这不起作用

时间:2010-03-29 15:33:05

标签: c++ c linux gcc g++

我有问题。我编写了示例代码,我想在没有错误的情况下构建它:

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

生成文件

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

生成文件

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

我做错了什么?

2 个答案:

答案 0 :(得分:10)

您正在编译C代码函数,但您希望链接C ++函数。

由于'类型安全链接',您提供的功能不是C ++代码调用的函数。

在test1.h中使用:

#ifdef __cplusplus
extern "C" {
#endif

extern void test1(void);

#ifdef __cplusplus
}
#endif

或者:

  • 使用C ++编译器编译该函数。

C ++编译器将破坏符号名称以提供类型安全链接(您应该能够通过首选搜索引擎搜索的术语)。

'编译器' - 实际上是链接器 - 正在寻找一个带有C ++错位名称的函数,该名称代表带有签名'void test1(void);'的C ++函数。

例如(但请记住 - 不同的编译器故意以不同的方式破坏事物),MacOS X 10.6.2上的G ++ 4.2.1为函数生成符号“__Z5test1v”; GCC生成符号“_test1”。显然,当链接器正在寻找“__Z5test1v”时,将不会使用符号“_test1” - 它拼写不相同。这是一件好事。

您可以在主程序的目标文件上使用'nm -g'来查看它正在查找的内容,并在库中的目标文件上查看它提供的内容。而且,鉴于拼写不同,这就是加载器没有拿起库函数的原因 - 它正在寻找具有不同名称的东西。

答案 1 :(得分:3)

您正在从C ++函数调用C函数。两者之间的命名是不同的(C ++ mangles名称包含参数信息)。

将头文件更改为如下所示:

#ifdef __cplusplus
extern "C" {
#endif

extern void test();

#ifdef __cplusplus
}
#endif

这将告诉编译器该函数遵循C命名/调用约定。