2012-01-25 77 views
4

我有一个程序做了一些图形。当我以交互方式运行它时,我希望它使用系统中的OpenGL来提供硬件加速图形。当我批量运行它时,我希望能够重定向它以使用Mesa GL库,以便我可以使用OSMesa功能渲染到屏幕外缓冲区。如果选择批量启动选项,则通过执行LoadLibrary/GetProcAddress启用OSMesa功能。有没有什么方法可以在Windows中模拟LD_LIBRARY_PATH?

在Linux上,它很容易使这项工作。通过使用一个包装脚本调用程序,我可以做这样的事情:

if [ "$OPTION" = "batch" ]; then 
    export LD_LIBRARY_PATH=$PATHTO/mesalibs:$LD_LIBRARY_PATH 
fi 

这是可能做到这一点在Windows的东西吗?

当我尝试添加目录到PATH变量,程序继续去系统OPENGL32.DLL。我可以让程序使用Mesa GL/OSMesa共享库的唯一方法是让它们与我的程序位于同一个目录中。但是,当我这样做时,该程序将永远不会使用系统opengl32.dll。

回答

4

如果我已经理解了你说的正确,在你的进程启动时加载了错误版本的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。

+0

延迟加载是关键,我也发现opengl32.dll和glu32.dll必须设置为延迟加载。我将可执行文件设置为延迟加载opengl32.dll和glu32.dll,然后将代码放在这两个DLL上调用LoadLibrary,如果程序以批处理模式启动的话。这段代码是在第一次调用Qt库之前插入的。 – likso

0

虽然这应该在cmd窗口是可能的,似乎你有没有运气。

尝试:在脚本中设置一个变量(RUNNING_IN_SCRIPT = Y),然后从安装的绝对路径解析可执行文件和LoadLibrary中的变量 - 确保在退出时清除变量。

+0

也许我不清楚 - 我只为osmesa32.dll做一个LoadLibrary。 opengl32.dll隐式链接。我试图找到一种方法来替换与Mesa opengl32.dll系统opengl32.dll。在Linux上,我可以使用LD_LIBRARY_PATH来做到这一点,但在Windows上,我认为我卡住了 - 但我希望不是。 – likso

+0

当然,当变量设置为'Y'时,只需调用LoadLibrary,否则跳过该代码。注意这不是一个很好的解决方案,但它会工作 – KevinDTimm

+0

这是我不明白的部分。可以说我的脚本设置了一个变量,然后以批处理模式启动我的程序。我的程序启动并自动加载系统opengl32.dll。当我的程序到达检查它是否以批处理模式启动的部分时,系统opengl32.dll已经加载。如果我现在尝试执行LoadLibrary(“H:\\ PATH \\ TO \\ mesa \\ opengl32.dll”),它如何替换已经加载的系统opengl32.dll? – likso

0

有几个方法,你可以解决这个问题,这取决于库和他们的名字/地点:

如果两个具有相同的名称(OPENGL32.DLL),那么你需要的DLL梅萨位置添加到搜索路径使得在之前搜索系统目录。订单目录被检入详细here。正如你所看到的,$PATH来到系统后面,所以你不能只是添加目录。但是,可以通过将工作目录设置为包含mesa文件的路径来使用第二步(“当前目录”)。通常这意味着在包含文件的目录中使用绝对路径启动应用程序。

虽然这仍然不是特别愉快。如果可以的话,应该使用LoadLibrary,并在应用程序启动时检查环境变量(OPENGL_LIBRARY_PATH)。假设从opengl32.dll和梅萨的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变量来缓存程序生命周期的结果。也可以为不同的库使用不同的函数名称,虽然这需要更多的逻辑,所以我会把细节留给你。

+0

是的,两者都有相同的名字,opengl32.dll。我已经尝试使用“当前目录” - 它不起作用。当前目录位于搜索顺序中的系统目录之后。我也想过修改代码来完成GetProcAddress,但这不是所期望的,因为所有的OpenGL调用都来自Qt库。目前,我正在使用相同的可执行文件驻留在不同目录中的愚蠢技术,其中一个具有Mesa库的目录驻留在可执行文件中,以便它们根据dll搜索顺序加载。 – likso

+0

有一个技巧可以使用,如果你确实知道你的库会在Qt之前加载(或者你可以创建一个存根,那么可以这样做):从那里调用所需库上的'LoadLibrary',这样一个加载的模块该名字在Qt库加载时存在。链接器将检查“opengl32.dll”,如果已经加载,请使用*表示*。否则,你将不得不使用加载顺序,并可能检查依赖项/进程跟踪工具它正在搜索的路径。 – ssube

+0

你有关于这个“诡计”的更多信息吗?我试图在一个简单的测试程序中做这样的事情(正如KevinDTimm所建议的那样),在那里我对Mesa opengl32.dll和osmesa32.dll做了LoadLibrary,然后调用OSMesaCreateContext,OSMesaMakeCurrent和glGetIntegerv。除非特意将Mesa库放在同一目录中,否则测试程序将始终抓取系统opengl32.dll。 – likso

0

Windows用于搜索动态库的不同路径,但由于安全考虑,系统路径首先被搜索。

你可以,但是使用延迟加载导入得到一个解决办法:如果你使用的MSVC

,你可以单出你感兴趣的装载在自己与/DELAYIMPORT标志链接器的DLL 。

然后,覆盖delay load helper function并使用LoadLibrary找到正确的DLL(并且不信任它到系统)。

加载正确的DLL后,让你的帮助函数调用原来的一个,它将自己做所有的GetProcAddress业务。

相关问题