.dll
或.so
是共享库(在运行时链接),而.a
和.lib
是静态库(在编译时链接)。这在Windows和Linux之间没有区别。
区别在于它们的处理方式。注意:区别仅在于使用习惯上的不同。要按照Windows的方式在Linux上进行构建,或者反过来,这并不太难,只是实际上几乎没有人这样做。
如果我们使用一个dll,或者甚至从我们自己的二进制文件中调用一个函数,有一种简单明了的方法。例如,在C语言中,我们可以看到:
int example(int x) {
...do_something...
}
int ret = example(42);
然而,在汇编级别上,可能会有许多差异。例如,在x86上,执行call
操作码,并在堆栈上给出42
。或者在某些寄存器中。或者任何地方。在编写dll之前,没有人知道它将如何使用。或者项目将如何使用它,可能是用现在甚至不存在的编译器(或语言!)编写的(或者对于dll的开发人员来说是未知的)。
例如,默认情况下,C和Pascal都从堆栈中放置参数(并获取返回值)-但它们按不同的顺序执行。您还可以通过一些-依赖于编译器的-优化,在寄存器之间交换函数中的参数。
正如您正确看到的那样,Windows的习惯是构建一个dll时,我们还会创建一个最小的.a
/.lib
。这个最小的静态库只是一个包装器,该dll的符号(函数)通过它被访问。这使得所需的汇编级别调用转换成为可能。
它的优点是兼容性。它的缺点是如果你只有一个.dll文件,你可能很难弄清楚它的函数应该如何调用。这使得使用dll成为一项麻烦的任务,如果dll的开发者没有给你提供 .a
。因此,它主要用于封闭性的目的,例如更容易获取SDK的额外现金。
另一个缺点是即使你使用动态库,你也需要静态编译这个小包装器。
在Linux中,dll的二进制接口是标准的,并遵循C约定。因此,不需要 .a
,并且共享库之间存在二进制兼容性,但我们没有Microsoft定制的优势。
LoadLibrary
的东西。参考: 将可执行文件链接到 DLL - Breno