操作系统是MacOS X,具体是在PowerPC G4上运行的10.5(Leopard),但我在运行10.6的x86上也遇到了同样的问题。
我正在编写一个动态加载DLL的应用程序。 DLL(我们称之为
现在,事实证明
一种解决方法是将
是否有一种编程方式可以覆盖
我正在编写一个动态加载DLL的应用程序。 DLL(我们称之为
foo.dylib
)是另一个应用程序的一部分,位于硬盘的其他位置;我的应用程序通过编程方式找到foo.dylib
(确切的位置可能会更改,可能用户通过从运行的应用程序本身的GUI指定DLL路径)。例如,假设我的应用程序位于目录/Application/MyApp.app/Contents/MacOS
中,并且foo.dylib
恰好位于/Application/OtherApp.app/Contents/MacOS
中。 DLL加载使用dlopen()
。现在,事实证明
foo.dylib
本身需要一堆其他DLL,这些DLL位于相同的目录中,但我事先不知道任何关于它们的信息。每个这样的额外DLL都在foo.dylib
中注册,其路径如@executable_path/bar.dylib
。 @executable_path
的语义是应替换为当前进程可执行文件所在的目录。对于OtherApp来说,这很好用,但对我来说不行:当我打开foo.dylib
时,它尝试加载bar.dylib
,并在/Application/MyApp.app/Contents/MacOS/bar.dylib
中查找它,这不是正确的目录。一种解决方法是将
DYLD_FALLBACK_LIBRARY_PATH
环境变量设置为/Application/OtherApp.app/Contents/MacOS
,但必须在启动我的应用程序之前执行此操作(该环境变量由动态链接器仅读取一次;使用setenv()
或putenv()
以编程方式更改其值没有效果)。这与动态发现foo.dylib
文件的位置不兼容。是否有一种编程方式可以覆盖
@executable_path
的效果?
dlopen
加载依赖项是行不通的:从dyld的角度来看,@executable_path/bar.dylib
和/Application/OtherApp.app/Contents/MacOS/bar.dylib
不是同一个文件(这里没有“SONAME”的概念;搜索DLL的路径作为DLL名称),因此dyld拒绝使用手动加载的bar.dylib
(我已经尝试过)。 - Thomas Pornin