在运行时按路径加载共享库

时间:2011-10-02 13:08:51

标签: c++ plugins shared-libraries

我正在构建一个Java应用程序,它使用用C ++编写的共享库,并针对不同的操作系统进行编译。问题是,这个共享库本身依赖于它通常在适当的环境变量(PATHLIBRARY_PATHLD_LIBRARY_PATH)下找到的附加库。

我可以 - 但不想 - 设置这些环境变量。我宁愿在运行时从给定路径加载所需的共享库 - 就像插件一样。不 - 我不希望任何启动应用程序在新环境中启动新进程。有人知道如何实现这个目标吗?

我知道这一定是可能的,因为我使用的库之一能够从给定路径加载其插件。当然我更喜欢与平台无关的代码,但如果不可能,Windows,Linux和MacOS的单独解决方案也会这样做。

修改 我应该提到我希望使用的共享库是面向对象的,这意味着单个函数的绑定不会这样做。

4 个答案:

答案 0 :(得分:26)

可以使用dlopen的Un UNIX / Linux系统。那么问题是您必须通过dlsym

获取所需的所有符号

简单示例:

typedef int (*some_func)(char *param);

void *myso = dlopen("/path/to/my.so", RTLD_NOW);
some_func *func = dlsym(myso, "function_name_to_fetch");
func("foo");
dlclose(myso);

将从那里加载.so并执行function_name_to_fetch()。有关详细信息,请参见手册页dlopen(1)。

答案 1 :(得分:10)

在Windows上,您可以使用LoadLibrary,在Linux上使用dlopen。 API非常相似,可以通过提供完整路径直接加载so / dll。如果它是运行时依赖项,则可以正常工作(加载后,您可以通过调用GetProcAddress / dlsym来“链接”。)

答案 2 :(得分:3)

我同意其他有关使用dlopen和LoadLibrary的海报。 libltdl为您提供了与这些功能无关的平台接口。

答案 3 :(得分:1)

我认为你不能为它做到这一点。

大多数Dll都有某种init()函数,必须在加载后调用,有时init()函数需要一些参数并返回一些句柄来调用dll的函数。你知道附加库的定义吗?

然后,第一个库只能通过使用其名称来查看DLL X是否在RAM中。它需要的可以是不同的目录或不同的版本/版本。如果完整路径与已经加载的另一个路径相同,操作系统将识别该库,它将共享它而不是第二次加载它。

另一个库可以从另一个路径加载它的插件,因为它写的不依赖于PATH而且它们是他自己的插件。

您是否尝试在加载Dll之前从代码更新进程的环境变量?这不取决于启动过程。