我正在开发一个库。该库将被编译为共享对象(.so)。要使用该库,https://www.cs.swarthmore.edu/~newhall/unixhelp/howto_C_libraries.html说我需要#include标头(.h)文件并链接共享库-lmylib。他们说头文件应该包含要使用的函数的函数原型,而函数的实际代码将在(.c)文件中。
我尝试编译我的代码时没有#include头文件,我从编译器收到和未定义的引用错误,但是当包含头时它会成功编译。
如果我放弃标题,我会得到隐式声明警告和未定义的引用错误:
warning: implicit declaration of function ‘printmatrix’
undefined reference to `printmatrix'
但是,我调用的lapack函数不需要头文件。它收到隐式声明警告,但没有错误:
warning: implicit declaration of function ‘dsyev_’
为什么我需要包含头文件?看来我将头文件合并到最终代码中两次,一次编译共享对象时再次编译可执行文件。我使用过其他库,例如lapack我可以在没有任何#include语句的情况下链接库。
答案 0 :(得分:3)
通常,标题应该只包含declerations:类型,结构,函数原型,类,模板等......而不是代码(除非它用于错误处理)。
标题很有用,因为它们允许您为库(.so)和库的接口(将使用共享对象的可执行文件)设置相同的确切声明。
为了成功完成链接,你的应用程序应该知道函数的调用约定:它可以是c风格的调用(cdecl),pascal风格(WINAPI),快速调用或其他 - 每个都有一个不同的呼叫方法。
如果您真的不想使用库标题,您还可以使用extern
关键字手动定义函数。它可能就像重新编写头文件一样(不推荐)。
例如,如果共享库具有add()
函数:
int add(int a, int b) {
return a + b;
}
并且您希望在没有标题的应用程序中使用该功能,您可以这样做:
extern int add(int, int);
int main() {
int a = 10, b = 20;
int r = add(a, b);
printf("%d + %d = %d\n", a, b, r);
return 0;
}
看来我将头文件合并到最终代码中两次,一次编译共享对象时再次编译可执行文件。
那应该怎么做。您应该在两个项目中包含相同的标题。大多数主要图书馆都这样做例如,请参阅libevent。