Is there any way to simulate LD_LIBRARY_PATH in Windows?

32.4k views Asked by At

I have a program do so some graphics. When I run it interactively, I want it to use OpenGL from the system to provide hardware accelerated graphics. When I run it in batch, I want to be able to redirect it to use the Mesa GL library so that I can use OSMesa functionality to render to an offscreen buffer. The OSMesa functionality is enabled by doing a LoadLibrary/GetProcAddress if the batch start up option is selected.

On Linux, its fairly easy to make this work. By using a wrapper script to invoke the program, I can do something like this:

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

It is possible to do something this in Windows?

When I try adding a directory to the PATH variable, the program continues to go to the system opengl32.dll. The only way I can get the program to use the Mesa GL/OSMesa shared libraries is to have them reside in the same directory as my program. However, when I do that, the program will never use the system opengl32.dll.

4

There are 4 answers

1
Harry Johnston On BEST ANSWER

If I've understood what you're saying correctly, the wrong version of opengl32.dll is being loaded when your process starts up, i.e., load-time dynamic linking. There is probably no good way to solve your problem without changing this.

You say you can't use conveniently use run-time dynamic linking (LoadLibrary/GetProcAddress) for opengl32.dll because the calls to it are coming from the Qt library. I presume that the Qt library is itself dynamically linked, however, so you should be able to solve your problem by using run-time linking for it. In this scenario, provided you load opengl32.dll before you load the Qt library, you should be able to explicitly choose which version of opengl32.dll you want to load.

You might want to consider using delayed loading in order to simplify the process of moving from load-time to run-time linking. In this scenario, the first call into the Qt library causes it to be loaded automatically, and you'll just need to explicitly load opengl32.dll first.

6
KevinDTimm On

Though this should be possible in the cmd window, it seems you're having no luck.

Try: set a variable in your script (RUNNING_IN_SCRIPT=Y) and then parse for that variable in your executable and LoadLibrary from the absolute path of installation - be sure to clear the variable when you exit.

5
ssube On

There are a few ways you could handle this, depending on the libraries and their names/locations:

If both have the same name (opengl32.dll), then you need to add the Mesa DLL location to the search path such that it is searched before the system directory. The order directories are checked in is detailed here. As you can see, $PATH comes last, after system, so you can't just add the directory to that. However, you can make use of the second step ("The current directory") by setting the working directory to a path containing the mesa files. Generally this means starting the application using an absolute path while in the directory containing the files.

That's still not particularly pleasant, though. If you can, you should use LoadLibrary and check for an environment variable (OPENGL_LIBRARY_PATH) when your app starts up. Assuming the exports from opengl32.dll and Mesa's DLL are the same, you can do something like:

void LoadExports()
{
    char location[MAX_PATH];
    getenv("OPENGL_LIBRARY_PATH", location);
    HMODULE oglLib = LoadLibrary(location);

    function1 = GetProcAddress(oglLib, "glVertex2f");
    ...
}

This will work perfectly fine, doing almost exactly what you want.

However, if you want to do that, you can't import opengl32.dll, which you're probably doing, you have to dynamically link throughout. Make sure not to link against opengl32.lib and you should be fine. Depending on how many functions you use, it may be a pain to set up, but the code can easily be scripted and only needs done once, you can also use static variables to cache the results for the lifetime of the program. It's also possible to use different function names for different libraries, although that takes a bit more logic, so I'll leave the details to you.

0
assafs On

Windows used to search different paths for dynamic libraries, but due to security consideration, the system path is searched first.

You could, however use Delay Load Imports to get a workaround:

If you're using MSVC, you could single-out the DLLs you're interested in loading on your own with /DELAYIMPORT flag to the linker.

Then, override the delay load helper function and use LoadLibrary to find the proper DLL (and not trust it to the system).

After loading the correct DLL, have your helper function just call the original one that will do all the GetProcAddress business by itself.