踩坑JNI

96
Zz鱼丸
2019.06.25 11:29* 字数 141

使用Android studio3.4.1,即最新版时。使用cmake调用opencv3.2的jni库,出现

[1/8] Building CXX object src/main/cpp/2_10_recognitionHQB/CMakeFiles/recognitionHQB.dir/__/inc/NL_Face_Recognition/NL_FaceRecognition.cpp.o
[2/8] Building CXX object src/main/cpp/2_10_recognitionHQB/CMakeFiles/recognitionHQB.dir/__/inc/NL_Face_aligner/aligner.cpp.o
[3/8] Building CXX object src/main/cpp/2_10_recognitionHQB/CMakeFiles/recognitionHQB.dir/__/inc/NL_Face_MultiAttr/NL_MultiAttrPrediction.cpp.o
[4/8] Building CXX object src/main/cpp/2_10_recognitionHQB/CMakeFiles/recognitionHQB.dir/faceRecognitionHQBAPI.cpp.o
[5/8] Building CXX object src/main/cpp/2_10_recognitionHQB/CMakeFiles/recognitionHQB.dir/recognitionHQB.cpp.o
[6/8] Building CXX object src/main/cpp/2_10_recognitionHQB/CMakeFiles/recognitionHQB.dir/__/inc/NL_Face_Detection/NL_FaceDetection.cpp.o
[7/8] Building CXX object src/main/cpp/2_10_recognitionHQB/CMakeFiles/recognitionHQB.dir/__/inc/NL_Face_MultiAttr/NL_MultiAttrPredictionUtil.cpp.o
[8/8] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\debug\obj\armeabi-v7a\librecognitionHQB.so
FAILED: cmd.exe /C "cd . && D:\AndroidSDK\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe  --target=armv7-none-linux-androideabi24 --gcc-toolchain=D:/AndroidSDK/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=D:/AndroidSDK/ndk-bundle/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -fno-addrsig -march=armv7-a -mthumb -mfpu=neon -Wa,--noexecstack -Wformat -Werror=format-security  -std=c++11 -fopenmp -O0  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--exclude-libs,libunwind.a -Wl,--no-undefined -Qunused-arguments -Wl,-z,noexecstack -shared -Wl,-soname,librecognitionHQB.so -o ..\..\..\..\build\intermediates\cmake\debug\obj\armeabi-v7a\librecognitionHQB.so @CMakeFiles/recognitionHQB.rsp  && cd ."
E:\Document\My\EmbedAI\AndroidSDK\NL_IDC_SDK\Project\NLFaceBaab\app\src\main\cpp\2_10_recognitionHQB/recognitionHQB.cpp:583: error: undefined reference to 'cv::imwrite(cv::String const&, cv::_InputArray const&, std::__ndk1::vector<int, std::__ndk1::allocator<int> > const&)'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(matrix.cpp.o):matrix.cpp:function std::vector<unsigned char, std::allocator<unsigned char> >::resize(unsigned int, unsigned char): error: undefined reference to 'std::__throw_length_error(char const*)'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(matrix.cpp.o):matrix.cpp:function std::vector<int, std::allocator<int> >::resize(unsigned int, int): error: undefined reference to 'std::__throw_length_error(char const*)'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(matrix.cpp.o):matrix.cpp:function std::vector<unsigned char, std::allocator<unsigned char> >::_M_fill_insert(__gnu_cxx::__normal_iterator<unsigned char*, std::vector<unsigned char, std::allocator<unsigned char> > >, unsigned int, unsigned char const&): error: undefined reference to 'std::__throw_length_error(char const*)'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(matrix.cpp.o):matrix.cpp:function std::vector<cv::Vec<unsigned char, 2>, std::allocator<cv::Vec<unsigned char, 2> > >::_M_fill_insert(__gnu_cxx::__normal_iterator<cv::Vec<unsigned char, 2>*, std::vector<cv::Vec<unsigned char, 2>, std::allocator<cv::Vec<unsigned char, 2> > > >, unsigned int, cv::Vec<unsigned char, 2> const&): error: undefined reference to 'std::__throw_length_error(char const*)'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.cpp:function _GLOBAL__sub_I_system.cpp: error: undefined reference to 'std::ios_base::Init::Init()'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.cpp:function _GLOBAL__sub_I_system.cpp: error: undefined reference to 'std::ios_base::Init::~Init()'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(ocl.cpp.o):ocl.cpp:function std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*) [clone .part.43]: error: undefined reference to 'std::basic_ios<char, std::char_traits<char> >::clear(std::_Ios_Iostate)'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(ocl.cpp.o):ocl.cpp:function std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf(): error: undefined reference to 'std::locale::~locale()'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(ocl.cpp.o):ocl.cpp:function std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf(): error: undefined reference to 'std::string::_Rep::_M_destroy(std::allocator<char> const&)'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(ocl.cpp.o):ocl.cpp:function std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf(): error: undefined reference to 'std::string::_Rep::_S_empty_rep_storage'

D:/opencv-3.2.0-android-sdk/OpenCV-android-sdk/sdk/native/libs/armeabi-v7a/libopencv_core.a(ocl.cpp.o):ocl.cpp:function std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::~basic_stringbuf(): error: undefined reference to 'vtable for std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >'

google得知是因为编译这些静态库时所用的编译器、标准库等跟NDK当前的版本不同。网上的建议都是stl改为gnustl_static或gnustl_shared之类。但是尝试之后均失败,经分析都是未定义的引用时是否抛出错误,因此更改build.gradle

添加-DANDROID_ALLOW_UNDEFINED_SYMBOLS=TRUE
cmake {
                arguments "-DANDROID_ARM_NEON=TRUE" ,
                        "-DANDROID_TOOLCHAIN=clang++",
                        "-DANDROID_STL=c++_static",
                        "-DANDROID_PLATFORM=android-24",
                        "-DANDROID_ALLOW_UNDEFINED_SYMBOLS=TRUE"
                cppFlags "-std=c++11 -fopenmp"
                abiFilters "armeabi-v7a"
            }
···
编译通过

如何在 gradle 中使用 cmake 的变量

android {
  ...
  defaultConfig {
    ...
    externalNativeBuild {
      cmake {
        cppFlags "-frtti -fexceptions" // 通常不在这里配置 cppFlags 了
        ...
        // 使用下面这种语法向变量传递参数:
        // arguments "-D变量名=参数".
        arguments "-DANDROID_ARM_NEON=TRUE",
        // 使用下面这种语法向变量传递多个参数(参数之间使用空格隔开):
        // arguments "-D变量名=参数1 参数2"
                  "-DANDROID_CPP_FEATURES=rtti exceptions"
      }
    }
  }
  buildTypes {...}
  
  externalNativeBuild {
    cmake {
        path "CMakeLists.txt"
    }
  }
}

CMake 编译 NDK 所支持的变量配置


图片.png

附表(C++ 库支持)

图片.png

参考:https://developer.android.com/ndk/guides/cpp-support#system

日记本