我有一个程序这样做一些图形。当我以交互方式运行它时,我希望它从系统中使用OpenGL来提供硬件加速图形。当我批量运行它时,我希望能够重定向它以使用Mesa GL库,以便我可以使用OSMesa功能渲染到屏幕外缓冲区。如果选择批量启动选项,则通过执行LoadLibrary / GetProcAddress来启用OSMesa功能。
在Linux上,使这项工作相当容易。通过使用包装器脚本来调用程序,我可以这样做:
if [ "$OPTION" = "batch" ]; then
export LD_LIBRARY_PATH=$PATHTO/mesalibs:$LD_LIBRARY_PATH
fi
可以在Windows中执行此操作吗?
当我尝试将目录添加到PATH变量时,程序继续转到系统opengl32.dll。我可以让程序使用Mesa GL / OSMesa共享库的唯一方法是让它们与我的程序驻留在同一目录中。但是,当我这样做时,程序将永远不会使用系统opengl32.dll。
答案 0 :(得分:5)
如果我已经理解了你说的正确,那么当你的进程启动时,就会加载错误版本的opengl32.dll,即load-time dynamic linking。没有改变这个问题,可能没有好办法解决你的问题。
你说你不能方便地使用run-time dynamic linking(LoadLibrary / GetProcAddress)来替换opengl32.dll,因为对它的调用来自Qt库。我认为Qt库本身是动态链接的,因此您应该能够通过使用运行时链接来解决问题。在这种情况下,如果您在加载Qt库之前加载opengl32.dll,您应该能够明确选择要加载的opengl32.dll版本。
您可能需要考虑使用delayed loading来简化从加载时间到运行时链接的过程。在这种情况下,第一次调用Qt库会导致它自动加载,你只需要先显式加载opengl32.dll。
答案 1 :(得分:1)
有几种方法可以解决这个问题,具体取决于库及其名称/位置:
如果两者具有相同的名称(opengl32.dll),则需要将Mesa DLL位置添加到搜索路径,以便在系统目录之前搜索。签入的订单目录详细here。如您所见,$PATH
在系统之后排在最后,因此您不能只将目录添加到该目录中。但是,您可以通过将工作目录设置为包含mesa文件的路径来使用第二步(“当前目录”)。通常,这意味着在包含文件的目录中使用绝对路径启动应用程序。
LoadLibrary
并在应用启动时检查环境变量(OPENGL_LIBRARY_PATH
)。假设opengl32.dll
和Mesa的DLL的导出是相同的,你可以这样做:
void LoadExports()
{
char location[MAX_PATH];
getenv("OPENGL_LIBRARY_PATH", location);
HMODULE oglLib = LoadLibrary(location);
function1 = GetProcAddress(oglLib, "glVertex2f");
...
}
这将完美无缺,几乎完全符合您的要求。
但是,如果您想这样做,则无法导入opengl32.dll
,您可能正在进行此操作,您必须动态链接。确保不要链接opengl32.lib
,你应该没问题。根据您使用的函数数量,设置可能会很麻烦,但代码可以轻松编写脚本并且只需要执行一次,您还可以使用static
变量来缓存程序生命周期的结果。也可以为不同的库使用不同的函数名称,虽然这需要更多的逻辑,所以我将把详细信息留给你。
答案 2 :(得分:0)
虽然这应该可以在cmd窗口中显示,但似乎你没有运气。
尝试:在脚本中设置一个变量(RUNNING_IN_SCRIPT = Y),然后从绝对安装路径解析可执行文件和LoadLibrary中的变量 - 确保在退出时清除变量。
答案 3 :(得分:0)
Windows用于搜索动态库的不同路径,但出于安全考虑,首先搜索系统路径。
但是,您可以使用延迟加载导入来获得解决方法:
如果你正在使用MSVC,你可以单独输出你有兴趣加载的DLL,并用/DELAYIMPORT
标志加载到链接器。
然后,覆盖delay load helper function并使用LoadLibrary
找到合适的DLL(而不是信任它到系统中)。
加载正确的DLL后,让你的帮助函数只调用原来会自行完成所有GetProcAddress
业务的函数。