我有问题。我编写了示例代码,我想在没有错误的情况下构建它:
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
我做错了什么?
答案 0 :(得分:10)
您正在编译C代码函数,但您希望链接C ++函数。
由于'类型安全链接',您提供的功能不是C ++代码调用的函数。
在test1.h中使用:
#ifdef __cplusplus
extern "C" {
#endif
extern void test1(void);
#ifdef __cplusplus
}
#endif
或者:
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命名/调用约定。