【发布时间】:2015-06-17 10:50:33
【问题描述】:
我在我的原生 android 应用程序中使用了一些静态预构建的静态库,一切正常。现在我想将我的静态库之一切换为 .so。通过在其 android.mk 中将 BUILD_STATIC_LIBRARY 替换为 BUILD_SHARED_LIBRARY 并添加所需的依赖项,我成功地构建了 .so 库。
我还能够通过在其 android.mk 中将相应的 PREBUILT_STATIC_LIBRARY 替换为 PREBUILT_SHARED_LIBRARY 来构建我的应用程序。生成的应用程序现在无法启动。我什至无法指出调试器附加到应用程序的位置。
除此之外,我不明白的是构建系统如何知道该函数应该从库中导入。我的so库应该导出一个函数,但我没有将它声明为dllexport/import之类的。我的应用程序中仍然没有未解析的符号(当我从列表中删除我的预构建库时,未解析的符号会按预期显示)。
另一个问题是我看到生成了两个 .so 文件。 obj/local/$(TARGET_ARCH_ABI) 文件夹中的一个大文件和 libs/$(TARGET_ARCH_ABI) 中的另一个小文件。在声明我的预建库时,我引用了 libs 文件夹中的第二个库。
我确实尝试在stackoverflow中搜索答案,并找到了很多相关的帖子:
- loading library (.so file) in android
- NDK - How to use a generated .so library in another project
- How to use .so file in Android code to use the native methods
- How to use libffmpeg.so in Android project?
但我看不到这些帖子与我的问题有什么关系,因为我可以成功构建甚至链接我的应用程序。
【问题讨论】:
-
当您的应用无法启动时。你在 logcat 中看到了什么吗?
-
确实,logcat 应该是您的首选。连接断点调试器(在 java 或本机级别)只是在日志未能使问题明显时才需要打扰 - 特别是当(正如您在此处发现的那样)问题似乎在您有机会之前发生时。虽然如果你真的想要,你可以在你的程序之前尝试加载本地库。
-
您正确地指向预建库的较小 (stripped) 副本。另一个可能对调试非常有用。
-
@Alex Cohn 我仍然不明白链接器如何理解符号应该动态解析。函数声明对此没有任何线索。在 Windows 中,您可以先显式地
LoadLibrary,然后再显式地GetProcAddress,或者将函数声明为__declspec(dllimport),它告诉链接器要做什么。这在 Linux/Android 上如何工作?我是否需要显式加载库(在 Java 或 C++ 中)?链接器如何识别导入的符号? -
链接器会查看您可以使用
nm -D列出的符号,如下面的答案所述。
标签: android c++ android-ndk