2012-01-25 127 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業務。

相關問題