Android本机运行时无法加载符号,即使它们实际上已在加载的.so文件中找到

时间:2017-10-24 06:27:00

标签: android c++ ffmpeg android-ndk

我使用NDK v15.2编译了ffmpeg v3.4,我正在创建一个名为ffmpeg-jni的包装器库。

static {
    try {
        System.loadLibrary("avutil");
        System.loadLibrary("avcodec");
        System.loadLibrary("avformat");
        System.loadLibrary("swscale");
        System.loadLibrary("avfilter");
        System.loadLibrary("ffmpeg-jni"); // Exception here line#101
        loadedLibraries = true;
    } catch (Throwable e) {
        e.printStackTrace();
    }
}

下面是加载我的包装器库时抛出的异常。

10-24 11:12:13.819 21499-21499/com.myeglu.android.canary.staging W/System.err: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "av_register_all" referenced by "/data/app/com.myeglu.android.canary.staging-2/lib/arm/libffmpeg-jni.so"...

但令我惊讶的是,这个函数是在libavformat.so中定义的,它已成功加载;从nm tool output可以清楚地看出,libavformat.so中定义了av_register_all()函数(T)

这是所有预先构建的库的链接,这些库在运行时很难实现和平。 (除了ffmpeg库之外还有一些其他库)

https://drive.google.com/drive/folders/0B20ExoMyOP_UeDhNdmwzc2tjR3M?usp=sharing

有人帮助我理解在这种情况下我可能会遗漏的内容。谢谢你的时间。

1 个答案:

答案 0 :(得分:1)

首先,您应该以正确的顺序明确列出所有需要的库,或者让系统解析依赖关系(如果您的平台至少是Lollipop)。

具体来说, libavcodec 需要 libswresample

ffmpeg-jni 似乎无法正确构建。其动态部分仅列出

0x00000001 (NEEDED) Shared library: [libandroid.so]
0x00000001 (NEEDED) Shared library: [libjnigraphics.so]
0x00000001 (NEEDED) Shared library: [libavcodec.so]
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libc.so]

此外, .dynsym 表包含

 5: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND av_register_all

我希望相反,

 5: 00000000     0 FUNC    GLOBAL DEFAULT  UND av_register_all@LIBAVFORMAT_57 (4)

请注意 avcodec_find_decoder 的符号类型以及来自库中 libavcodec.so 的其他引用是正确的。

您是否已将{{1>}用于 libffmpeg-jni.so

更新:实际上,cmake使用Android工具链编写的LOCAL_ALLOW_UNDEFINED_SYMBOLS=trueCMAKE_SHARED_LINKER_FLAGS传递给链接器;通过覆盖此变量,您实际上允许未定义的符号(并丢失了一些针对Android调整的其他重要标志)。最重要的是,重写CMAKE标准变量是危险的。