【问题标题】:How to call unknown function from dynamic library?如何从动态库中调用未知函数?
【发布时间】:2014-07-09 13:26:34
【问题描述】:

我需要实现从 .so 调用函数的能力,而无需在编译时了解该函数。我只会在运行时提供这些信息。我该怎么做?

我们可以假设我要调用的函数是从库中导出的,库端不需要做任何事情。

函数签名在编译时未知。

操作系统是 Raspberry PI 上的 Linux。

【问题讨论】:

  • 我认为您想要实现的目标可以使用 [libffi](sourceware.org/libffi)
  • 如果“没有任何知识”的意思是你甚至没有它的签名,你会如何使用它?
  • 希望不是launch_nukes函数
  • Quentin:确切地说,函数签名在编译时是未知的。
  • @Quentin:通常通过传递也在运行时提供的参数。

标签: c++ c shared-libraries


【解决方案1】:

dlopendlsym(或它们的 Windows 等效项)允许您加载文件名在运行时确定的“共享对象”(编译代码的模块),然后检索其 名称的子例程的函数指针 也是在运行时确定的。但是,每个此类函数的类型签名——要传递的参数的数量和类型——仍然必须在编译时知道,以便您可以转换 dlsym 返回的 void *到正确的函数指针类型,然后调用它。

如果您不知道要在运行时之前传递的参数的数量和类型,那么 dlopendlsym 是不够的,事实上,这仍然是需要的东西之一 em> 少量的手写汇编语言。在 C 或 C++ 中,即使使用常见的编译器扩展,也根本无法合成其参数列表在运行时确定的调用。 (GCC 的扩展听起来像就是为了这个,但是除了深入 GCC 自己的运行时库之外,它们还不够通用,无法派上用场。)

幸运的是,有人已经为您编写了汇编语言并将其封装在一个不错的库中:libffi。它是可靠的、获​​得许可的,并且支持您可能关心的每个 CPU 以及更多。在 x86 上,它还可以方便地消除 Unix 和 Windows 之间的一些差异。

【讨论】:

  • 谢谢,libffi 似乎非常适合这项任务 :)
【解决方案2】:

听起来你需要在 linux 上使用 late binding

您可以使用dlopen 加载您的共享库,然后使用dlsym 获取您的函数(前提是您知道函数的名称)。

之后,您将需要使用您的签名信息来正确调用该函数(在编译时,您通常会将该指针转换为适当的类型)。

注意:这不能跨不同的操作系统移植。

【讨论】:

  • 在 Windows 上等价于 LoadLibraryGetProcAddress
  • -1。签名已知的假设是错误的,并跳过了最难的部分。
猜你喜欢
  • 2011-02-18
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-18
  • 1970-01-01
  • 2019-10-07
相关资源
最近更新 更多