【问题标题】:Can I have a dynamic library required only when used by the code?我可以拥有仅在代码使用时才需要的动态库吗?
【发布时间】:2015-01-20 17:37:40
【问题描述】:

我有一个大型程序,可能会链接到一些外部库,但这些只是某些特定功能所需要的。但是,即使我不使用这些功能,仍然需要外部库。我可以做一些事情(最好在编译或链接时),以便仅在请求它们提供的功能时才需要这些库?

例子:

你好.c

#include <stdio.h>
#include <unistd.h>
extern const char *myfunc();

main() {
  int z;
  char buf[32];
  z = gethostname(buf,sizeof buf);
  if (strcmp(buf,"#!#!#!#!#") == 0) {
    printf("%s\n", myfunc());
  } else {
    printf("%s\n", "No library used");
  }
  return 0;
}

shrobj.c:

const char *myfunc() {
  return "Hello World";
}

编译为:

$ gcc -fpic -c shrobj.c
$ gcc -shared -o libshared.so shrobj.o
$ gcc hello.c -lshared -L.
$ ./a.out 
./a.out: error while loading shared libraries: libshared.so: cannot open shared object file: No such file or directory

而我的主机名显然不是#!#!#!#!#

$ LD_LIBRARY_PATH=. ./a.out 
No library used

所以,我想要的是能够在没有库的情况下运行“./a.out”(无论出于何种原因,它可能不可用),只要它的函数没有被调用。

我已经看到可以使用dlopen() 获得延迟加载,但是,即使上面的示例是用 C 语言编写的,我的大部分代码也是用 fortran 编写的,尤其是可能调用库中函数的部分。

【问题讨论】:

  • 你到底在问什么?是的,您可以使用 dlopen() 延迟加载,直到您需要它时才需要该库...
  • @ElliottFrisch 我在问是否可以通过其他不需要修改源代码的方式来完成
  • 我不知道。

标签: linux ld


【解决方案1】:

Linux 已经可以通过其内核 API 做到这一点;具体来说,dlopen(3) 函数。如果您想了解详细信息,请使用man 查找。

基本上,您使用要加载的库的名称调用dlopen,它会返回库的句柄,您需要保存以供以后使用。

void* lib = dlopen("./lib.so"); // this can be any path

要从这个库中加载一个函数,您可以使用dlsym 函数,并将它的返回值分配给一个函数指针,然后您可以像在程序中的任何其他函数一样调用它(嗯,大多数情况下)。

int (*func)() = dlsym(lib, "thing");

当你完成后,你需要告诉内核你已经完成了这个库:

dlclose(lib)

为简洁起见,我在这里省略了错误检查,但您需要在实际代码中进行。

这样做意味着除非需要,否则您的程序不会尝试加载库,因此如果所需的库或依赖项未安装或丢失,您的代码可以检测到并使用其他内容。您的程序(只要编写正确)不会在启动时崩溃,但如果您非常依赖该库并且无法找到它,您可能不得不退出并出现错误。

【讨论】:

  • 感谢您提供详细信息。其中有多少是特定于 linux 的?它如何与 fortran 一起工作?
  • @Jellby 对不起,如果我不清楚。该函数是 GNU C 库的一部分;它不是特定于 Linux 的。事实上,它也适用于 OS X 和 FreeBSD。
  • @Jellby 我不能说它是否适用于 Fortran,因为我从未使用过 Fortran。对不起。
猜你喜欢
  • 2022-11-16
  • 1970-01-01
  • 2018-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-06
  • 2012-06-19
  • 2017-09-19
相关资源
最近更新 更多