SQLAPI++:获取可执行文件加载的共享库的路径

SQLAPI++: Get path to shared library loaded by executable

SQLAPI++ 有一个不寻常的功能,您可以设置一个字符串来告诉它在哪里可以找到 ODBC 共享库。在我的例子中,这是 libtdsodbc.so,我的应用程序实际上在构建时链接了该库,但在运行时这不足以让 SQLAPI++ 工作。

我的代码是:

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

ODBC.LIBSdocumented 这样的:

Forces SQLAPI++ Library to use specified ODBC manager library.

如果将 LD_LIBRARY_PATH 设置为包含 libtdsodbc.so 的目录,则上述代码有效。但如果你不这样做,Connect() 就会失败:

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

如果您将 ODBC.LIBS 设置为完整路径而不仅仅是文件名,它会再次起作用。但是应用程序怎么知道是哪条路径呢?

我的应用程序(在 SQLAPI++ 之外)通过其在构建时设置的 RUNPATH 找到 libtdsodbc.so。此路径不是 /usr/lib 之类的系统路径。我想让 SQLAPI++ 使用在运行时加载到应用程序中的同一个库。

一个想法是应用程序到 inspect its own RUNPATH,搜索 libtdsobc.so,然后使用该路径。但这需要相当多的繁琐代码来基本上重新实现 ld.so 已经做的事情。

我不想在构建时将路径与 RUNPATH 分开写入可执行文件,因为我有时会在部署前编辑 RUNPATH(然后我需要编辑两件事).

理想情况下,我想告诉 SQLAPI++ 只使用已经加载的库。我可以通过 运行 lsof -p PID | grep libtdsodbc.so 找出这条路径,但是可执行文件中的 运行 shell 命令不是一个好的解决方案(而且我不想重新实现 lsof).

您可以使用 dl_iterate_phdr(link 还包含打印库名称的示例代码)或手动解析 /proc/self/maps.