问题标签 [dlopen]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
2954 浏览

c - 调用 dlclose 时共享库中的全局变量会发生什么情况?

如果通过 dlopen 和 dlclose 机制使用共享库(或 DLL),并且如果创建的共享库有一些全局变量,其内存来自堆,那么调用 dlclose 时这些变量和内存会发生什么?

如果在同一进程中,再次调用 dlopen,会是什么行为?

0 投票
1 回答
244 浏览

c - 使用 dlopen() 对象时确定调用对象

我正在编写一个 (C) 程序,它通过 dlopen() 使用插件系统。我遇到的绊脚石是主程序导出了一些真正需要知道调用它们的插件的函数(主要是记录保存,因此插件可以正确卸载,因为它们向主程序添加函数指针之类的东西程序)。

我似乎找不到一种干净的方法来做到这一点。到目前为止我提出的选项:

  1. 要求插件提供其名称,或者我在加载时提供的一些数据作为函数的参数。
    • 我不喜欢这个选项,因为不是所有的函数都关心它们是从谁调用的,所以它使它不一致和混乱。另外,我想让插件尽可能难以谎报它是谁
  2. 使用 backtrace() 确定前一个函数的对象名称。
    • 这看起来相当丑陋且不可移植。
  3. 要求插件放置一个包含其名称的文件级结构(或其他变量)(我们称之为“plugin_info”进行讨论)。然后在加载插件时使用 dlsym() 来查找变量并按其名称对其进行索引(如在哈希中)。然后放入插件用来调用函数的#define 宏,并将宏添加&plugin_info为参数。
    • 这就是我现在正在使用的,但它看起来很hackish。对于一个你必须有宏传递'&plugin_info',如果你只是传递'plugin_info'那么它会从主程序中提取'plugin_info',而不是插件。通过地址引用它似乎可以使它用正确的编译,并且它不会被重新定位。这让我不喜欢这个选项,因为这似乎是它未定义的行为,但它确实有效。此外,当插件开发人员遇到函数调用问题(传递错误的参数类型或诸如此类的东西)时,宏也会让人有点困惑。

如果有任何其他想法或技术,我很想知道。

0 投票
2 回答
2416 浏览

c - 使用 MinGW 防止在 C(不是 C++)中进行名称修改以进行动态符号搜索

我有一个 C 程序,我在其中通过函数名称“动态”获取函数指针(即,我将函数名称作为字符串传递并获取指向函数的指针)。我已经在 Linux 中使用 dlopen 和 dlsym 做到了这一点,我想它也可以在任何其他类 Unix 中使用dlfcn

当我尝试使用 MinGW 将该程序移植到 Windows 时,问题就开始了。当我尝试使用“GetProcAddress(handle, symbol_name)”查找名称时,其中“symbol_name”是我的回调函数的名称,“handle”是“GetModuleHandle(NULL)”返回的当前可执行文件的句柄,我什么也没得到因为 MinGW 名称修饰在我的符号名称中添加了一个“_”。

显而易见的解决方案(在我想要的符号前加上“_”)对于可移植性似乎有点“危险”(编译器可以为其中一些添加两个下划线吗?我不知道),所以,我问:

  • 有更好的方法来防止编译器对我的符号进行名称修改吗?(或其中的一个子集,只有我需要动态查找的回调);

  • 或者一种让 GetProcAddress 即使在损坏时也能找到它们的方法?

我还尝试了选项-fno-leading-underscore,但它也删除了所有外部符号的修饰,使程序无法与 stdlib 等链接(另外,文档上的警告有点吓人)。

另外,请注意我使用的是纯 C——我的代码的任何部分都没有 C++——我所有的代码都存在于一个“.exe”中。

TIA

0 投票
1 回答
5323 浏览

linker - 如何实现符号版本控制

我想实现以下目标:

我有多个版本的库。我使用 dlopen() 动态加载最新版本的库。然后我想查看该版本中是否存在特定函数(以及类似的返回类型和参数列表)。如果确实如此,则将其打开,否则将回退到以前的版本进行检查。

我看过一些关于“版本脚本”的帖子,但无法使用它。另外我认为搜索符号表不是一个解决方案,因为它只检查那里的函数名。

0 投票
2 回答
6347 浏览

ios - 在 iOS 中使用 dlsym 按名称调用函数

我不能在 iOS 中按名称调用函数吗?我有一个名为getstring. 我这样称呼它:

当它执行时,responseFiled.text设置为dlsym(...): symbol not found。这意味着dlopen有效但无效dlsymnm我使用并看到存在的二进制文件中的符号_getstring。我检查了手册dlsym它说我不应该在名称中添加下划线。无论如何添加它并不能解决问题。我究竟做错了什么?

我在这里问过一个关于在 Objective-C 中按名称调用函数的类似问题,然后在 Mac 上按照答案成功尝试,所以这个问题似乎是 iOS 特有的。

0 投票
3 回答
5409 浏览

c++ - typeinfo、共享库和不带 RTLD_GLOBAL 的 dlopen()

使用dlopen加载共享库时,我遇到了一些异常无法正常运行的问题(或者至少,正如我所希望的那样;我知道这有问题)。我在这里包含了一些简化的示例代码。实际情况是myapp =Matlab, myext1 =mexglx matlab 扩展,mylib是我的代码在两个扩展之间的共享库(myext1 , myext2

mylib.h

mylib.cpp

myext1.cpp

myext2.cpp与myext1.cpp 相同

我的应用程序.cpp

编译这段代码:

A处对entrypoint()的调用按预期工作,throwFoo()抛出异常,entrypoint()捕获它。然而,在B处的调用未能捕捉到异常。添加更多诊断代码表明Foo类的 typeinfo 在两个扩展中不同。更改两个dlopen调用的顺序没有区别,第二个加载的扩展失败。

我知道我可以通过使用RTLD_GLOBAL作为dlopen的附加标志来解决这个问题,但是使用 dlopen 的应用程序(Matlab)是我无法控制的。我可以用mylibmyext1myext2 做些什么来解决这个问题吗?

我必须避免在运行时使用 LD 标志(因为我无法控制运行 Matlab 二进制文件的用户)。还有其他建议吗?

0 投票
5 回答
13478 浏览

c - 从内存中打开?

我正在寻找一种直接从内存加载生成的目标代码的方法。

我知道如果我将它写入文件,我可以调用 dlopen 来动态加载其符号并链接它们。但是,考虑到它从内存中开始,写入磁盘,然后由 dlopen 重新加载到内存中,这似乎有点绕道。我想知道是否有某种方法可以动态链接内存中存在的目标代码。据我所知,可能有几种不同的方法可以做到这一点:

  1. 欺骗 dlopen 认为您的内存位置是一个文件,即使它永远不会离开内存。

  2. 找到其他一些系统调用来做我正在寻找的东西(我认为这不存在)。

  3. 找一些可以直接在内存中链接代码的动态链接库。显然,这有点难以搜索,因为“动态链接库”提供了有关如何动态链接库的信息,而不是有关执行动态链接任务的库的信息。

  4. 从链接器中抽象出一些 API,并在其代码库中创建一个新库。(显然这对我来说是最不理想的选择)。

那么其中哪些是可能的?可行的?你能指出我假设存在的任何事情吗?还有其他我什至没有想到的方法吗?

0 投票
1 回答
858 浏览

c++ - 为什么这个动态库加载代码可以和 gcc 一起工作?

背景:

我发现自己承担着将 C++ GNU/Linux 应用程序移植到 Windows 的艰巨任务。此应用程序所做的一件事是在特定路径上搜索共享库,然后使用 posix dlopen() 和 dlsym() 调用动态地从中加载类。我们有充分的理由以这种方式加载,我不会在这里讨论。

问题:

要动态发现由 C++ 编译器使用 dlsym() 或 GetProcAddress() 生成的符号,必须使用 extern "C" 链接块来解开它们。例如:

此代码是完全有效的 C++,可在 Linux 和 Windows 上的众多编译器上编译和运行。但是,它不能与 MSVC 一起编译,因为“返回类型不是有效的 C”。我们想出的解决方法是更改​​函数以返回指向列表的指针而不是列表对象:

我一直在尝试为 GNU/Linux 加载程序找到一个最佳解决方案,该解决方案既可以与新函数和旧旧函数原型一起使用,也可以至少检测何时遇到不推荐使用的函数并发出警告。如果代码只是在尝试使用旧库时出现段错误,这对我们的用户来说是不合适的。我最初的想法是在调用 get_list 期间设置一个 SIGSEGV 信号处理程序(我知道这很恶心 - 我愿意接受更好的想法)。因此,为了确认加载旧库会出现段错误,我认为它会使用旧函数原型(返回列表对象)通过新加载代码(需要指向列表的指针)运行库,令我惊讶的是刚刚工作。我的问题是为什么

下面的加载代码适用于上面列出的两个函数原型。我已经确认它可以在 Fedora 12、RedHat 5.5 和 RedHawk 5.1 上使用 gcc 版本 4.1.2 和 4.4.4。使用带有 -shared 和 -fPIC 的 g++ 编译库,并且可执行文件需要与 dl (-ldl) 链接。

0 投票
1 回答
1920 浏览

c++ - 在 C++ 中,可以从动态库中访问外部定义的全局变量吗?

在 C++ 中,可以从动态库中访问外部定义的全局变量吗?

我在头文件中声明了一个全局变量,如下所示;

文件名:TestVariable.hpp

然后在源代码文件中定义如下;

文件名:TestVariable.cpp

构成我的动态库的源代码如下;

文件名:插件.cpp

然后我的主要功能定义如下;

文件名:main.cpp

我可以使用 GNU Autotools、g++ 和 ld 正确编译和链接所有代码(并且没有任何警告),但是当我运行生成的二进制可执行文件时,它无法 dlopen 动态库文件。但是,如果我注释掉包含函数loadLibrary主体的唯一一行代码,然后重新编译和链接,则程序可以正常工作!

如果我不知道更好,我会说当 dlopen 调用它(库)时,库无法解析其对全局变量testVariable的引用,这就是导致 dlopen 操作失败的原因。链接类型和/或名称修饰可能与此问题有关吗?

如果我在生成的动态库上运行 Linux nm 实用程序,它会通知我符号testVariable未定义,即“U”。如果我在二进制可执行文件上运行 nm 实用程序,它会通知我符号testVariable存在并驻留在未初始化的数据部分中,即“B”。那么为什么dlopen在加载动态库的时候不能解析这个符号呢?

我只从源文件Plugin.cpp生成动态库。二进制可执行文件是从 2 个源代码文件main.cppTestVariable.cpp 生成的。

有人可以帮忙吗。我可以发誓答案是盯着我的脸,但我只是没有看到它。

提前致谢。

0 投票
2 回答
3925 浏览

macos - 在使用 dlopen() 加载的 DLL 中覆盖 @executable_path

操作系统是 MacOS X,特别是 PowerPC G4 上的 10.5 (Leopard),但我在运行 10.6 的 x86 上遇到了同样的问题。

我正在编写一个动态加载 DLL 的应用程序。DLL(我们称它为foo.dylib)是另一个应用程序的一部分,位于硬盘的其他位置;我的应用程序foo.dylib以编程方式找到(确切的位置可能会改变,可能用户通过 GUI 从正在运行的应用程序本身指定 DLL 路径)。例如,假设我的应用程序位于 directory 中/Application/MyApp.app/Contents/MacOS,并且foo.dylib恰好位于/Application/OtherApp.app/Contents/MacOS. DLL 加载使用dlopen().

现在,事实证明,它foo.dylib本身需要一堆其他 DLL,它们位于同一目录中,但我事先对此一无所知。每个这样的额外 DLL 都foo.dylib使用诸如@executable_path/bar.dylib. 的语义@executable_path是它应该被找到当前进程可执行文件的目录替换。这对 OtherApp 非常有用,而不是对我:当我打开时foo.dylib,它会尝试加载bar.dylib,它会在/Application/MyApp.app/Contents/MacOS/bar.dylib不正确的目录中查找它。

一种解决方法是将DYLD_FALLBACK_LIBRARY_PATH环境变量设置为/Application/OtherApp.app/Contents/MacOS,但这必须启动我的应用程序之前完成(该环境变量仅由动态链接器读取一次;以编程方式更改其值setenv()putenv()无效)。这与文件位置的动态发现不兼容foo.dylib

是否有一种编程方式来覆盖 的效果@executable_path