C++ 中 dlsym() 和 dlopen() 的替代品
我有一个应用程序,其中一部分使用共享库。 这些库在编译时链接。
在运行时,加载程序期望共享对象位于 LD_LIBRARY_PATH 中,如果没有找到,整个应用程序将崩溃并出现错误“无法加载共享库”。请注意,不能保证客户端将拥有库,在这种情况下,我希望应用程序留下合适的错误消息,独立部分也应该正常工作。
为此,我使用 dlsym()
和 dlopen()
来使用共享库中的 API。 问题是,如果 API 中有很多函数,我必须使用 dlsym() 和 ptr 单独访问它们,在我的例子中,这会导致内存损坏和代码崩溃。
有其他选择吗?
I have an application a part of which uses shared libraries. These libraries are linked at compile time.
At Runtime the loader expects the shared object to be in the LD_LIBRARY_PATH
, if not found the entire application crashes with error "unable to load shared libraries".Note that there is no guarantee that client would be having the library, in that case I want the application to leave a suitable error message also the independent part should work correctly.
For this purpose I am using dlsym()
and dlopen()
to use the API in the shared library. The problem with this is if I have a lot of functions in the API, i have to access them Individually using dlsym()
and ptrs which in my case are leading to memory corruption and code crashes.
Are there any alternatives for this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
解决问题的常见方法是声明一个函数指针表,执行单个 dlsym() 来查找它,然后通过指向该表的指针调用所有其他函数。 示例(未经测试):
PS 使用 dlsym 和指针单独访问 API 函数本身不会导致内存损坏和崩溃。 很可能你只是遇到了错误。
编辑:
您可以对第三方库使用完全相同的技术。 创建一个
libdrmaa_wrapper.so
并将api_table
放入其中。 将包装器直接链接到libdrmaa.so
。在主可执行文件中,
dlopen("libdrmaa_wrapper.so", RTLD_NOW)
。 当(且仅当)libdrmaa.so
在运行时存在并提供您在api_table
中使用的所有 API 函数时,此 dlopen 才会成功。 如果成功,只需一次dlsym
调用即可让您访问整个 API。The common solution to your problem is to declare a table of function pointers, to do a single dlsym() to find it, and then call all the other functions through a pointer to that table. Example (untested):
P.S. Accessing your API functions individually using dlsym and pointers does not in itself lead to memory corruption and crashes. Most likely you just have bugs.
EDIT:
You can use this exact same technique with a 3rd-party library. Create a
libdrmaa_wrapper.so
and put theapi_table
into it. Link the wrapper directly againstlibdrmaa.so
.In the main executable,
dlopen("libdrmaa_wrapper.so", RTLD_NOW)
. Thisdlopen
will succeed if (and only if)libdrmaa.so
is present at runtime and provides all API functions you used in theapi_table
. If it does succeed, a singledlsym
call will give you access to the entire API.您可以用另一个应用程序包装您的应用程序,该应用程序首先检查所有必需的库,如果缺少某些内容,它会很好地出错,但如果一切正常,它会执行真正的应用程序。
You can wrap your application with another one which first checks for all the required libraries, and if something is missing it errors out nicely, but if everything is allright it execs the real application.
使用以下类型的代码
使用
dlopen()
在运行时加载此库。并使用 dlsym() 并调用 getDynLibPointer() 来返回 DynLib 对象。
从这个对象中,您可以访问所有函数 jst 作为
obj.fun1()
.....这是早期提出的 C++ 风格的结构方法。
Use below type of code
use
dlopen()
for loading this library at runtime.and use
dlsym()
and callgetDynLibPointer()
which returns DynLib object.from this object you can access all your functions jst as
obj.fun1()
.....This is ofcource a C++ style of struct method proposed earlier.
您可能正在 Linux 上寻找某种形式的延迟库加载。 它不是开箱即用的,但您可以通过创建一个小型静态存根库来轻松模仿它,该存根库将在第一次调用它的任何函数时尝试
dlopen
所需的库(发出诊断消息和如果 dlopen 失败则终止),然后将所有调用转发给它。此类存根库可以手动编写、由项目/库特定的脚本生成或由通用工具 Implib 生成。所以:
You are probably looking for some form of delay library load on Linux. It's not available out-of-the-box but you can easily mimic it by creating a small static stub library that would try to
dlopen
needed library on first call to any of it's functions (emitting diagnostic message and terminating ifdlopen
failed) and then forwarding all calls to it.Such stub libraries can be written by hand, generated by project/library-specific script or generated by universal tool Implib.so:
你的问题是,未解析符号的解析是很早就完成的 - 在Linux上,我相信数据符号在进程启动时解析,而函数符号是延迟完成的。 因此,根据您未解析的符号以及您正在进行的静态初始化类型,您可能没有机会进入您的代码。
我的建议是有一个包装应用程序来捕获返回代码/错误字符串“无法加载共享库”,然后将其转换为更有意义的内容。 如果这是通用的,则不需要在每次添加新的共享库时都进行更新。
或者,您可以让包装器脚本运行
ldd
,然后解析输出,ldd
将报告未找到特定应用程序的所有库。Your problem is that the resolution of unresolved symbols is done very early on - on Linux I believe the data symbols are resolved at process startup, and the function symbols are done lazily. Therefore depending on what symbols you have unresolved, and on what sort of static initialization you have going on - you may not get a chance to get in with your code.
My suggestion would be to have a wrapper application that traps the return code/error string "unable to load shared libraries", and then converts this into something more meaningful. If this is generic, it will not need to be updated every time you add a new shared library.
Alternatively you could have your wrapper script run
ldd
and then parse the output,ldd
will report all libraries that are not found for your particular application.