链接共享对象库而不包括它

时间:2018-01-24 22:09:26

标签: c

我正在开发一个库。该库将被编译为共享对象(.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语句的情况下链接库。

1 个答案:

答案 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