我正在尝试使用C ++创建和链接静态库。我有两个文件:
helloWorld.cpp
#include <iostream>
int main(int argc, char const *argv[]) {
std::cout << "I'm inside main." << '\n';
printHello();
return 0;
}
libraryHello.cpp
#include <iostream>
void printHello() {
std::cout << "Hello" << '\n';
}
我正在运行此类命令(基于http://www.techytalk.info/c-cplusplus-library-programming-on-linux-part-one-static-libraries/):
g++ -Wall -c libraryHello.cpp -o libraryHello.o
ar rcs libmylib.a libraryHello.o
g++ -static helloWorld.cpp -L. -lmylib -o helloExecute
前两个顺利,当尝试编译主文件时出现这样的错误:
helloWorld.cpp: In function ‘int main(int, const char**)’:
helloWorld.cpp:5:14: error: ‘printHello’ was not declared in this scope
看起来它根本没有加载,也找不到printHello。在编译,链接或其他任何东西时,我有什么问题吗?我想要做的是使用静态库从main调用printHello()过程并将其链接到helloWorld.cpp。
我的编译器:g ++ 5.4.0,操作系统:Ubuntu 16.04 32位
答案 0 :(得分:3)
您在使用前未声明该功能:
#include <iostream>
void printHello(); /// <-- this was missing
int main(int argc, char const *argv[]) {
std::cout << "I'm inside main." << '\n';
printHello();
return 0;
}
您拥有链接所需的一切,但不适合编译。一般的想法是这样的:编译器需要为您使用的每个函数提供声明。也就是说,它必须知道它的名字和签名。
编译器现在将检查函数调用是否对给定签名有效,并为函数调用留下占位符。链接器可以解析这些占位符并将其替换为被调用函数的实际地址。
因此,链接器必须为该函数找到匹配的定义,即实际的实现。如果您只是声明该函数,但忘记定义它,编译将很快成功,但链接器会抱怨未解析的引用。
这种拆分允许您独立编译不同的源文件:每个源文件都需要知道它使用的每个函数的声明,而不是定义。这足以让编译器确保调用者正确使用该函数。声明通常放在头文件中,以确保实现和调用者对函数签名的一致性有一致的了解,即使它们位于不同的源文件中。
答案 1 :(得分:2)
helloWorld.cpp
#ifndef LIBRARYHELLO_H
#define LIBRARYHELLO_H
void printHello();
#endif // LIBRARYHELLO_H
libraryHello.h(您需要添加此文件)
#include <iostream>
#include <libraryHello.h>
void printHello() {
std::cout << "Hello" << '\n';
}
libraryHello.cpp
OSError: [Errno 13] Permission denied: '/Users/myusername/Library/Python/2.7'
答案 2 :(得分:0)
你仍然需要有
的前瞻性声明 void printHello();
在main()
之前。
否则编译器不知道应该如何调用该函数。
通常的方法是将其放入相应的头文件中,并将其包含在其他翻译单元中。