erlang nif共享库上的未定义符号

Posted

技术标签:

【中文标题】erlang nif共享库上的未定义符号【英文标题】:Undefined symbols on erlang nif shared library 【发布时间】:2015-03-08 06:22:27 【问题描述】:

我在尝试将我的共享库(一个 erlang nif)链接到另一个使用 dlopen 加载其他共享库(插件)的共享库(libpurple)时遇到问题。

问题是 mylib.so 链接到 libpurple.so,libpurple.so 使用 dlopen 加载 plugins.so,而 plugins.so 无法从 libpurple.so 中找到符号

1> mylib:init().
ok
2> /usr/lib/erlang/erts-6.3/bin/beam.smp: symbol lookup error: /usr/lib/purple-2/libmyspace.so: undefined symbol: purple_account_option_string_new

我正在编译:

gcc -fPIC -shared `pkg-config --cflags --libs purple` -I /usr/lib/erlang/erts-6.3/include -o priv/mylib.so c_src/mylib.c

看起来问题是在 erlang:load_nif 上调用了 dlopen,此代码与 erlang nif 有相同的问题,RTLD_NOW | RTLD_GLOBAL 修复了它,但我无法更改 erlang 调用 dlopen 的方式...

#include <dlfcn.h>
#include <stdio.h>
#include <glib.h>

void (*purple_util_set_user_dir)(const char *dir);
void (*purple_debug_set_enabled)(gboolean enabled);
gboolean (*purple_core_init)(const char *ui);

int main()

  void* lib = dlopen("/usr/lib/libpurple.so", RTLD_LAZY);
  purple_util_set_user_dir = dlsym(lib, "purple_util_set_user_dir");
  purple_debug_set_enabled = dlsym(lib, "purple_debug_set_enabled");
  purple_core_init = dlsym(lib, "purple_core_init");

  purple_util_set_user_dir("/tmp/purpletest");
  purple_debug_set_enabled(TRUE);
  purple_core_init("test");

  return 0;

我开始工作的唯一解决方法是像LD_PRELOAD=/usr/lib/libpurple.so erl 这样调用erlang,但远非理想。

看起来同样的问题,使用 RTLD_GLOBAL 解决,https://developer.pidgin.im/ticket/7872

【问题讨论】:

也许你需要将libpurple静态链接到mylib.so @SteveVinoski 我希望有另一种方法.. libpurple 是一个大库,我不想自己将其重建为静态版本 【参考方案1】:

Erlang VM 不加载带有暴露全局符号的 NIF 库是有充分理由的 - 它会不可挽回地污染全局命名空间。

理论上,我不知道这是否总是正确的,插件应该能够动态加载其父库以查找其符号,而不会导致操作系统加载另一个图像图书馆。

【讨论】:

以上是关于erlang nif共享库上的未定义符号的主要内容,如果未能解决你的问题,请参考以下文章

Cython:共享对象中的未定义符号

如何检测二进制/库中的未定义符号?

静态库中的未定义符号链接到动态库

MAC OS X 10.8 上的 gcc 4.8 抛出“架构 x86_64 的未定义符号:”

如何解决 NSScanner 上的“架构 x86_64 的未定义符号”? react-native 中的 Swift pod

mac上的架构x86_64错误的未定义符号