3

我试图以一种抽象的方式来阐述这个问题,但无论如何我最后都会提供有关实际库的详细信息。

动态库与在汇编中有一些代码的Addon其他库静态链接,WebRTC并且该代码与自己的目标WebRTC文件一起作为目标文件链接到WebRTC。让我们称之为汇编代码VP8。的功能在里面VP8标明。一些函数from调用函数,最终调用函数 from 。externWebRTCEncode()AddonWebRTCVP8

现在,Firefox要加载库的应用程序Addon非常复杂,并且有自己的库版本(意味着静态链接)WebRTC(我们称之为WebRTC2),但版本较旧。

所以,这里有一个问题:如果Encode()从应用程序调用FirefoxWebRTC函数会被调用(不是WebRTC2,这是正确的)但是WebRTC试图调用VP8函数时,它们是从WebRTC2版本调用的(意味着应用程序的版本WebRTC),而不是从WebRTC.

有没有办法强制WebRTC只从本地副本拨打电话VP8

应用程序Firefox是一个 Firefox 浏览器,WebRTC是一个 WebRTC 库,VP8是一个 VP8 编解码器库(在 WebRTC 内部),并且Addon是我的 Firefox C++ 插件。

更新 - 详细说明

这是问题的“非抽象”描述:所以有一个 C++ XPCOM 插件,它与最新版本的 WebRTC 库静态链接。在附加组件内部的某个时刻,调用了对帧进行编码(类方法EncodeVP8Encoder,它一直在 Firefox 中崩溃,同时继续在使用 gtest 框架的测试程序上运行良好。

问题是,在 WebRTC 内部的某个时刻,有 VP8 汇编代码被调用以进行编码,并且该汇编代码的函数被声明为extern在实现文件中。实际上,它在vp8_intra_pred_y_ve_sse2功能上崩溃了。我比较了这个函数的三个汇编代码:一个来自我的 WebRTC 版本(用于附加组件),第二个 - 调试器崩溃的地方,第三个 - 来自 Mozilla 的 WebRTC 的源代码。

事实证明,出于某种奇怪的原因,调用了 Mozilla 的代码而不是加载项的 WebRTC(当然它们都具有相同的名称),并且由于 Mozilla 的 WebRTC 代码已过时,它会因 EXC_BAD_ACCESS 而崩溃。

4

1 回答 1

1

这可能对您没有太大帮助,但是由于没有其他人响应,所以我开始...

你没有提到你是在 Linux、Windows 还是其他东西上运行。我的答案是针对 Linux 的。我相信 Windows 以不同的方式加载动态库。

我认为发生的事情是您已经静态链接到 WebRTC 库存根接口,并且这些存根接口动态链接到实际实现,然后将 WebRTC 库的第一个实例加载到 firefox 中,而不是第二个。确保您真正链接到 WebRTC 库的静态编译版本。

linux手册页列出了一个有趣的标志,如果您的库是加载 WebRTC 库的库dlopen(3),这似乎会有所帮助:

   void *dlopen(const char *filename, int flag);

dlopen()

  The function dlopen() loads the dynamic library file named by the null-
  terminated  string  filename  and  returns  an  opaque "handle" for the
  dynamic library. [...]

  RTLD_DEEPBIND (since glibc 2.3.4)

      Place the lookup scope of the symbols in this library  ahead  of
      the global scope.  This means that a self-contained library will
      use its own symbols in preference to  global  symbols  with  the
      same  name contained in libraries that have already been loaded.
      This flag is not specified in POSIX.1-2001.

不幸的是,Firefox 是加载你的库的那个。

如果您的库与 WebRTC 动态链接(它似乎是)并且您使用带有 RTLD_DEEPBIND 标志的 dl_open() 显式加载了您想要的 WebRTC 库,那么这将解决您的问题。

这对您没有多大帮助,因为它不是绑定到的代码vp8_intra_pred_y_ve_sse2,但值得指出的是 gcc 还具有dlsym()可以采用几个特殊标志的功能:

   void *dlsym(void *handle, const char *symbol);

dlsym()

   The  function dlsym() takes a "handle" of a dynamic library returned by
   dlopen() and the null-terminated symbol  name,  returning  the  address
   where  that  symbol is loaded into memory. [...]

   There are two special pseudo-handles, RTLD_DEFAULT and RTLD_NEXT.   The
   former  will  find the first occurrence of the desired symbol using the
   default library search order.  The latter will find the next occurrence
   of  a  function  in  the  search order after the current library.  This
   allows one to provide a wrapper around a  function  in  another  shared
   library.

你可以在你的代码中使用它来至少调试正在发生的事情,方法是让它打印出它为查找 vp8_intra_pred_y_ve_sse2 获得的值。

最后,同一个手册页指出,linux 也有一个dlvsm()带有版本字符串参数的,允许 XPCOM 代码指定它想要的函数版本:

   #define _GNU_SOURCE         /* See feature_test_macros(7) */
   #include <dlfcn.h>

   void *dlvsym(void *handle, char *symbol, char *version);

如果是我,我被迫动态链接这些东西,我会采用蛮力方法。进入库并更改函数名称(在两个库中)。它并不优雅,每当任何一个库的新版本出现时都会让人头疼,但它简单直接。

于 2013-09-20T00:02:49.733 回答