Question

J'ai un programme le faire des graphiques. Lorsque je l'exécute de manière interactive, je veux qu'il utilise OpenGL à partir du système pour fournir des graphiques accélérés matériels. Lorsque je l'exécute en lot, je veux pouvoir le rediriger pour utiliser la bibliothèque Mesa GL afin que je puisse utiliser la fonctionnalité OSMESA pour rendre un tampon hors écran. La fonctionnalité OSMESA est activée en faisant un chargeur de chargement / getProcaddress si l'option de démarrage par lots est sélectionnée.

Sur Linux, il est assez facile de faire ce travail. En utilisant un script wrapper pour invoquer le programme, je peux faire quelque chose comme ceci:

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

Il est possible de faire quelque chose dans Windows?

Lorsque j'essaie d'ajouter un répertoire à la variable de chemin, le programme continue d'aller au système OpenGL32.dll. La seule façon dont je peux faire en sorte que le programme utilise les bibliothèques partagées MESA GL / OSMESA est de les faire résider dans le même répertoire que mon programme. Cependant, lorsque je fais cela, le programme n'utilisera jamais le système OpenGL32.dll.

Était-ce utile?

La solution

Si j'ai compris ce que vous dites correctement, la mauvaise version d'OpenGL32.dll est chargée lorsque votre processus démarre, c'est-à-dire lien dynamique de chargement. Il n'y a probablement aucun bon moyen de résoudre votre problème sans changer cela.

Vous dites que vous ne pouvez pas utiliser de manière pratique lien dynamique d'exécution (LoadLibrary / GetProcAddress) pour OpenGL32.dll car les appels sont venus de la bibliothèque QT. Je suppose que la bibliothèque QT est elle-même liée dynamiquement, vous devriez donc pouvoir résoudre votre problème en utilisant un lien d'exécution pour cela. Dans ce scénario, à condition de charger OpenGL32.dll avant de charger la bibliothèque QT, vous devriez pouvoir choisir explicitement la version d'OpenGL32.dll que vous souhaitez charger.

Vous voudrez peut-être envisager d'utiliser chargement retardé Afin de simplifier le processus de passage du temps de chargement au lien d'exécution. Dans ce scénario, le premier appel dans la bibliothèque QT fait le charger automatiquement, et vous aurez juste besoin de charger explicitement OpenGL32.dll d'abord.

Autres conseils

Il y a quelques façons de gérer cela, selon les bibliothèques et leurs noms / emplacements:

Si les deux ont le même nom (OpenGL32.dll), vous devez ajouter l'emplacement de DLL Mesa au chemin de recherche de telle sorte qu'il est recherché avant de le répertoire système. Les répertoires de commande sont enregistrés est détaillé ici. Comme tu peux le voir, $PATH Vient en dernier, après le système, vous ne pouvez donc pas simplement ajouter le répertoire à cela. Cependant, vous pouvez utiliser la deuxième étape ("le répertoire actuel") en définissant le répertoire de travail sur un chemin contenant les fichiers MESA. Généralement, cela signifie démarrer l'application à l'aide d'un chemin absolu dans le répertoire contenant les fichiers.

Ce n'est pas encore particulièrement agréable, cependant. Si vous le pouvez, vous devez utiliser LoadLibrary et vérifiez une variable d'environnement (OPENGL_LIBRARY_PATH) Lorsque votre application démarre. En supposant les exportations de opengl32.dll Et la DLL de Mesa est la même, vous pouvez faire quelque chose comme:

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

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

Cela fonctionnera parfaitement, faisant presque exactement ce que vous voulez.

Cependant, si vous voulez faire ça, vous ne pouvez pas importer opengl32.dll, ce que vous faites probablement, vous devez lier dynamiquement tout au long. Assurez-vous de ne pas vous connecter opengl32.lib Et ça devrait aller bien. Selon le nombre de fonctions que vous utilisez, cela peut être difficile à configurer, mais le code peut facilement être scénarisé et ne doit être fait qu'une seule fois, vous pouvez également utiliser static Variables pour mettre en cache les résultats de la durée de vie du programme. Il est également possible d'utiliser différents noms de fonction pour différentes bibliothèques, bien que cela prenne un peu plus de logique, donc je vous laisse les détails.

Bien que cela devrait être possible dans la fenêtre CMD, il semble que vous n'ayez pas de chance.

Essayez: Définissez une variable dans votre script (running_in_script = y), puis analysez cette variable dans votre exécutable et LoadLibrary à partir du chemin absolu de l'installation - assurez-vous d'effacer la variable lorsque vous sortez.

Windows utilisé pour rechercher différents chemins pour les bibliothèques dynamiques, mais en raison de la considération de sécurité, le chemin du système est d'abord recherché.

Vous pouvez cependant utiliser les importations de chargement de retard pour obtenir une solution de contournement:

Si vous utilisez MSVC, vous pouvez distinguer les DLL que vous souhaitez charger par vous-même /DELAYIMPORT Flag au linker.

Ensuite, remplacez le Retarder la fonction de charge d'assistance et utilise LoadLibrary pour trouver la DLL appropriée (et ne pas lui faire confiance au système).

Après avoir chargé la DLL correcte, demandez à votre fonction d'assistance d'appeler l'original qui fera tout le GetProcAddress affaires par elle-même.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top