如何在 Android 本机构建中正确支持不同的 C++ STL
How to correctly support different C++ STL's in Android Native Builds
老实说,我知道所有 C++ 依赖项都必须在 Android 项目中使用相同的 C++ STL 和 Ndk 进行编译,如 here 所示。但是如果我有很多支持不同 C++ STL 和 NDK 版本的依赖项怎么办。听起来好像没什么用。我相信一定有准确的方法。
首先,情况是有一个 android 项目构建了很多 c++ 库(可能超过 3 个)。这些支持不同的 C++ STL 和 Ndk。不知何故,这些依赖关系一直有效,直到出于某些目的决定重新构建。比如构建老版本v8(v4.9)支持stlport,POCO支持gnustl等
顺便说一句,我已经试过了;
- 使用特定的 STL 构建依赖项(失败)
- 将不同的 STL 作为共享库添加到依赖项中,例如 (Android.mk);
include $(CLEAR_VARS)
LOCAL_MODULE := stlportshared
LOCAL_SRC_FILES := $(LOCAL_PATH)/../../../src/main/jniLibs/$(TARGET_ARCH_ABI)/libstlport_shared.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_SRC_FILES := $(LOCAL_PATH)/../../../libsnative/x86/release/libv8-7dc15a4d5e.a
else
LOCAL_SRC_FILES := $(LOCAL_PATH)/../../../libsnative/armeabi/release/libv8-7dc15a4d5e.a
endif
LOCAL_MODULE := v8
LOCAL_SHARED_LIBRARIES := stlportshared
include $(PREBUILT_STATIC_LIBRARY)
实际 APP_STL 在 Application.mk
中是 gnustl_shared
注意:没有编译错误,但运行时崩溃。崩溃是 null dereferences 。打算问一些肤浅的问题,但我可以为好奇的人转发崩溃的详细信息。
首先,有非常充分的理由使用最新版本的 NDK。 r20 在写这篇文章的时候,幸运的是只支持两个 STL 变体:c++_shared 和 c++_static.
组织原生库的最简单方法是使用 c++_shared.
构建它们
我了解到您在使用此方法时遇到了一些问题。解决这些问题可能会对长期 运行 有所帮助,因为这些问题可能是代码中某些内部问题的症状。
但如果你做不到,也不要灰心。
你的应用程序可以安全地使用不同的 mative 库,每个库都有自己的 STL,只要它不混合这些原生库。如果 Java class A 在 libA.so 和 class 中有本地方法B 有自己的 libB.so,没有来自 libA.so[=41= 的调用] 到 libB.so 或者相反,你不应该关心哪个 STL 被 libA.so 和哪个 - 被 libB.so.
此外,如果你有在libP.so中调用C函数的本地库libQ.so,那么你不关心是libP还是libQ 完全使用 STL,或者它们各自使用哪个 STL。但如果这些 C 函数不是伪装的 C++ 函数,情况就是如此。它们不应传递 C++ 对象(包括 std::string)。它们不应接收或 return 指向 C++ 对象的指针(即使 C API 使用 reinterpret_cast for void *.
请注意,对于大多数实际用途,使用 c++_static 构建的库的规则是相同的。两个这样的库不应将 C++ 对象从一个传递到另一个。
老实说,我知道所有 C++ 依赖项都必须在 Android 项目中使用相同的 C++ STL 和 Ndk 进行编译,如 here 所示。但是如果我有很多支持不同 C++ STL 和 NDK 版本的依赖项怎么办。听起来好像没什么用。我相信一定有准确的方法。
首先,情况是有一个 android 项目构建了很多 c++ 库(可能超过 3 个)。这些支持不同的 C++ STL 和 Ndk。不知何故,这些依赖关系一直有效,直到出于某些目的决定重新构建。比如构建老版本v8(v4.9)支持stlport,POCO支持gnustl等
顺便说一句,我已经试过了;
- 使用特定的 STL 构建依赖项(失败)
- 将不同的 STL 作为共享库添加到依赖项中,例如 (Android.mk);
include $(CLEAR_VARS) LOCAL_MODULE := stlportshared LOCAL_SRC_FILES := $(LOCAL_PATH)/../../../src/main/jniLibs/$(TARGET_ARCH_ABI)/libstlport_shared.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) ifeq ($(TARGET_ARCH_ABI),x86) LOCAL_SRC_FILES := $(LOCAL_PATH)/../../../libsnative/x86/release/libv8-7dc15a4d5e.a else LOCAL_SRC_FILES := $(LOCAL_PATH)/../../../libsnative/armeabi/release/libv8-7dc15a4d5e.a endif LOCAL_MODULE := v8 LOCAL_SHARED_LIBRARIES := stlportshared include $(PREBUILT_STATIC_LIBRARY)
实际 APP_STL 在 Application.mk
中是 gnustl_shared注意:没有编译错误,但运行时崩溃。崩溃是 null dereferences 。打算问一些肤浅的问题,但我可以为好奇的人转发崩溃的详细信息。
首先,有非常充分的理由使用最新版本的 NDK。 r20 在写这篇文章的时候,幸运的是只支持两个 STL 变体:c++_shared 和 c++_static.
组织原生库的最简单方法是使用 c++_shared.
构建它们我了解到您在使用此方法时遇到了一些问题。解决这些问题可能会对长期 运行 有所帮助,因为这些问题可能是代码中某些内部问题的症状。
但如果你做不到,也不要灰心。
你的应用程序可以安全地使用不同的 mative 库,每个库都有自己的 STL,只要它不混合这些原生库。如果 Java class A 在 libA.so 和 class 中有本地方法B 有自己的 libB.so,没有来自 libA.so[=41= 的调用] 到 libB.so 或者相反,你不应该关心哪个 STL 被 libA.so 和哪个 - 被 libB.so.
此外,如果你有在libP.so中调用C函数的本地库libQ.so,那么你不关心是libP还是libQ 完全使用 STL,或者它们各自使用哪个 STL。但如果这些 C 函数不是伪装的 C++ 函数,情况就是如此。它们不应传递 C++ 对象(包括 std::string)。它们不应接收或 return 指向 C++ 对象的指针(即使 C API 使用 reinterpret_cast for void *.
请注意,对于大多数实际用途,使用 c++_static 构建的库的规则是相同的。两个这样的库不应将 C++ 对象从一个传递到另一个。