2017-04-20 3 views
0

SQLAPI ++ possède une fonction inhabituelle dans laquelle vous définissez une chaîne pour indiquer où trouver la bibliothèque partagée ODBC. Dans mon cas c'est libtdsodbc.so, et mon application lie réellement cette bibliothèque au moment de la construction, mais au moment de l'exécution ce n'est pas suffisant pour que SQLAPI ++ fonctionne.SQLAPI ++: Récupère le chemin d'accès à la bibliothèque partagée chargée par l'exécutable

Mon code est:

SAConnection conn; 
    conn.setOption("ODBC.LIBS") = "libtdsodbc.so"; 
    conn.Connect("SERVER=...", "", "", SA_ODBC_Client); 

ODBC.LIBS est documented comme ceci:

Forces SQLAPI ++ Bibliothèque pour utiliser la bibliothèque de gestionnaire ODBC spécifié.

Le code ci-dessus fonctionne si vous définissez LD_LIBRARY_PATH dans un répertoire contenant libtdsodbc.so. Mais si vous ne le faites pas, Connect() échoue:

libtdsodbc.so: cannot open shared object file: No such file or directory 

DBMS API Library 'libtdsodbc.so' loading fails 
This library is a part of DBMS client installation, not SQLAPI++ 
Make sure DBMS client is installed and 
this required library is available for dynamic loading 

Linux/Unix: 
1) The directories in the user's LD_LIBRARY_PATH environment variable 
2) The list of libraries cached in /etc/ld.so.cache 
3) /usr/lib, followed by /lib 

Il fonctionne à nouveau si vous définissez ODBC.LIBS à un chemin complet plutôt que juste un nom de fichier. Mais comment l'application peut-elle savoir quel chemin?

Mon application (en dehors de SQLAPI ++) trouve libtdsodbc.so via son RUNPATH qui est défini au moment de la construction. Ce chemin n'est pas un chemin système comme /usr/lib. Je voudrais que SQLAPI ++ utilise la même bibliothèque qui est chargée dans l'application lors de l'exécution.

Une idée est pour l'application à inspect its own RUNPATH, recherchez libtdsobc.so et utilisez ce chemin. Mais cela nécessite un peu de code fiddly pour réimplémenter fondamentalement ce que fait déjà ld.so.

Je ne veux pas faire le chemin dans l'exécutable au moment de la construction séparément de RUNPATH, parce que je modifie parfois RUNPATH avant le déploiement (et puis j'ai besoin de modifier deux choses).

Idéalement, je voudrais dire à SQLAPI ++ d'utiliser simplement la bibliothèque qui est déjà chargée. Je peux comprendre ce chemin en exécutant lsof -p PID | grep libtdsodbc.so mais exécuter des commandes shell à partir de l'exécutable n'est pas une bonne solution (et encore une fois je préfèrerais ne pas réimplémenter lsof).

Répondre

1

Vous pouvez utiliser dl_iterate_phdr (le lien inclut également un exemple de code qui affiche les noms de bibliothèques) ou analyser manuellement /proc/self/maps.