Android ndk 编译opencv后部分接口std::__ndk1与项目std::__1不匹配

发布于:2025-05-01 ⋅ 阅读:(12) ⋅ 点赞:(0)

1、opencv-4.11预编译命令(在opencv4.5.0之后兼容免费features2d做特征匹配),NDK版本选用的android-ndk-r23c-linux.zip

cmake -G Ninja \
-DCMAKE_TOOLCHAIN_FILE=/home/who/Downloads/NDK/android-ndk-r23c/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=arm64-v8a \
-DANDROID_PLATFORM=android-31 \
-DANDROID_ARM_NEON=ON \
-DANDROID_STL=c++_shared \
-DCMAKE_CXX_FLAGS="-D_LIBCPP_ABI_NAMESPACE=__1 -D_LIBCPP_ABI_VERSION=1 -frtti -fexceptions -D__GXX_RTTI=1" \
-DENABLE_RTTI=ON \
-DENABLE_EXCEPTIONS=ON \
-DBUILD_SHARED_LIBS=ON\
-DOPENCV_EXTRA_MODULES_PATH=/home/who/Downloads/opencv-4.11/opencv_contrib/opencv_contrib-4.11.0/modules \
-DBUILD_LIST=features2d,core,imgproc,imgcodecs,videoio,highgui,calib3d,flann,stitching,photo \
-DBUILD_opencv_stitching=ON \
-DBUILD_opencv_features2d=ON \
-DBUILD_opencv_core=ON \
-DBUILD_opencv_imgproc=ON \
-DBUILD_opencv_imgcodecs=ON \
-DBUILD_opencv_videoio=ON \
-DBUILD_opencv_highgui=ON \
-DBUILD_opencv_calib3d=ON \
-DBUILD_opencv_flann=ON \
-DBUILD_opencv_photo=ON \
-DWITH_OPENCL=ON \
-DOPENCL_LIBRARY=/home/who/Downloads/opencv-4.11/vendor/lib64/libGLES_mali.so \
-DWITH_VULKAN=ON \
-DVULKAN_LIBRARY=/home/who/Downloads/opencv-4.11/system/lib64/libvulkan.so \
-DENABLE_NEON=ON \
-DBUILD_JPEG=ON \
-DBUILD_ANDROID_PROJECTS=OFF \
-DBUILD_JAVA=OFF \
-DBUILD_opencv_java=OFF \
-DBUILD_opencv_java_bindings_generator=OFF \
-DBUILD_ANDROID_EXAMPLES=OFF \
-DBUILD_TESTS=OFF \
-DWITH_TBB=ON \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-O3 -mcpu=cortex-a76 -mtune=cortex-a76 -funsafe-math-optimizations -g" \
..

其他配置包括:

     -DANDROID_ABI=arm64-v8a 设置64位库,如需要32位可以设置为armeabi-v7a;
     -DCMAKE_CXX_FLAGS 符号兼容;
     -DANDROID_STL=c++_shared  std命名空间依赖库,默认为c++_static.a
     -DOPENCV_EXTRA_MODULES_PATH 画面拼接需要的外部库;
     -DBUILD_SHARED_LIBS 开启动态库打包;
     -DWITH_OPENCL=ON \ -DOPENCL_LIBRARY \ -DWITH_VULKAN=ON \ -DVULKAN_LIBRARY 用于开启GPU处理配置;
     -DCMAKE_CXX_FLAGS 编译优化器;

采用ninja做并行编译,加速编译速度;
编译安装:ninja -j16 && ninja install

2、使用命令llvm-nm -gDC libopencv_features2d.so | grep “cv::DescriptorMatcher::knnMatch”

$ llvm-nm -gDC libopencv_features2d.so | grep "cv::DescriptorMatcher::knnMatch"
0005b5e4 T cv::DescriptorMatcher::knnMatch(cv::_InputArray const&, std::__ndk1::vector<std::__ndk1::vector<cv::DMatch, std::__ndk1::allocator<cv::DMatch> >, std::__ndk1::allocator<std::__ndk1::vector<cv::DMatch, std::__ndk1::allocator<cv::DMatch> > > >&, int, cv::_InputArray const&, bool)
0005b440 T cv::DescriptorMatcher::knnMatch(cv::_InputArray const&, cv::_InputArray const&, std::__ndk1::vector<std::__ndk1::vector<cv::DMatch, std::__ndk1::allocator<cv::DMatch> >, std::__ndk1::allocator<std::__ndk1::vector<cv::DMatch, std::__ndk1::allocator<cv::DMatch> > > >&, int, cv::_InputArray const&, bool) const

$ llvm-nm -gDC libopencv_imgcodecs.so | grep "cv::imwrite"
000da7b0 T cv::imwrite(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&, cv::_InputArray const&, std::__ndk1::vector<int, std::__ndk1::allocator<int> > const&)

可以看到接口符号是std::__ndk1,而当设备使用的std::__1符号编译。
这会导致这些接口应编译报错


ld.lld: error: undefined symbol: cv::DescriptorMatcher::knnMatch(cv::_InputArray const&, cv::_InputArray const&, std::__1::vector<std::__1::vector<cv::DMatch, std::__1::allocator<cv::DMatch> >, std::__1::allocator<std::__1::vector<cv::DMatch, std::__1::allocator<cv::DMatch> > > >&, int, cv::_InputArray const&, bool) const
>>> referenced by

3、修改NDK,重新编译opencv

<1> 修改NDK中的__config文件

who@who-virtual-machine:~/Downloads/NDK/android-ndk-r23c$ find -name __config
./toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/c++/v1/experimental/__config
./toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/c++/v1/__config
./sources/cxx-stl/llvm-libc++/include/experimental/__config
./sources/cxx-stl/llvm-libc++/include/__config

./toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/c++/v1/__config
./sources/cxx-stl/llvm-libc++/include/__config

这两个文件中ndk删去
在这里插入图片描述
<2>、替换NDK中libc++__shared.so
需要替换的路径

$ find -name libc++_shared.so
./toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/i686-linux-android/libc++_shared.so
./toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/libc++_shared.so
./toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so
./toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so
./sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++_shared.so
./sources/cxx-stl/llvm-libc++/libs/x86_64/libc++_shared.so
./sources/cxx-stl/llvm-libc++/libs/x86/libc++_shared.so

替换的库为需要合入的设备下libc++.so

 # find -name libc++.so
./system/apex/com.android.adbd/lib/libc++.so
./system/apex/com.android.adbd/lib64/libc++.so
./system/apex/com.android.art/lib/libc++.so
./system/apex/com.android.art/lib64/libc++.so
./system/apex/com.android.media/lib/libc++.so
./system/apex/com.android.media/lib64/libc++.so
./system/apex/com.android.runtime/lib/libc++.so
./system/apex/com.android.runtime/lib64/libc++.so
./system/apex/com.android.conscrypt/lib/libc++.so
./system/apex/com.android.conscrypt/lib64/libc++.so
./system/apex/com.android.media.swcodec/lib64/libc++.so
./system/apex/com.android.vndk.current/lib/libc++.so
./system/apex/com.android.vndk.current/lib64/libc++.so
./system/apex/com.android.i18n/lib/libc++.so
./system/apex/com.android.i18n/lib64/libc++.so
./system/apex/com.android.appsearch/lib64/libc++.so
./system/lib/libc++.so
./system/lib64/libc++.so

替换后同时重命名库为libc++_shared.so

下面是替换重新编译opencv:

$ llvm-nm -gDC libopencv_imgcodecs.so | grep "cv::imwrite"
000000000013d220 T cv::imwriteanimation(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, cv::Animation const&, std::__1::vector<int, std::__1::allocator<int> > const&)
000000000013be50 T cv::imwrite(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, cv::_InputArray const&, std::__1::vector<int, std::__1::allocator<int> > const&)

$ llvm-nm -gDC libopencv_features2d.so | grep "cv::DescriptorMatcher::knnMatch"
0000000000086570 T cv::DescriptorMatcher::knnMatch(cv::_InputArray const&, std::__1::vector<std::__1::vector<cv::DMatch, std::__1::allocator<cv::DMatch> >, std::__1::allocator<std::__1::vector<cv::DMatch, std::__1::allocator<cv::DMatch> > > >&, int, cv::_InputArray const&, bool)
0000000000086300 T cv::DescriptorMatcher::knnMatch(cv::_InputArray const&, cv::_InputArray const&, std::__1::vector<std::__1::vector<cv::DMatch, std::__1::allocator<cv::DMatch> >, std::__1::allocator<std::__1::vector<cv::DMatch, std::__1::allocator<cv::DMatch> > > >&, int, cv::_InputArray const&, bool) const

可以看到重新编译后opencv库已经可以兼容std::__1

参考链接
https://blog.csdn.net/weixin_41660527/article/details/135130517


网站公告

今日签到

点亮在社区的每一天
去签到