我正在构建一个Java应用程序,它使用用C ++编写的共享库,并针对不同的操作系统进行编译。问题是,这个共享库本身依赖于它通常在适当的环境变量(PATH
,LIBRARY_PATH
或LD_LIBRARY_PATH
)下找到的附加库。
我可以 - 但不想 - 设置这些环境变量。我宁愿在运行时从给定路径加载所需的共享库 - 就像插件一样。不 - 我不希望任何启动应用程序在新环境中启动新进程。有人知道如何实现这个目标吗?
我知道这一定是可能的,因为我使用的库之一能够从给定路径加载其插件。当然我更喜欢与平台无关的代码,但如果不可能,Windows,Linux和MacOS的单独解决方案也会这样做。
修改 我应该提到我希望使用的共享库是面向对象的,这意味着单个函数的绑定不会这样做。
答案 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之前从代码更新进程的环境变量?这不取决于启动过程。