opencv交叉编译android库

在android studio中使用时,会出现如下错误

undefined reference to `cv::imwrite(cv::String const&, cv::_InputArray const&, std::__ndk1::vector const&)’
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

这个错误不是编译的错误,因为通过查看动态库的符号表,imwrite是有定义的,更奇怪的是imread的使用是正常的,这就完全不符合makefile的编译逻辑了。我把imwrite函数重写去vector参数的传入,再编译使用,imwrite正常写了,但是这样能解决这个问题,但其他函数还有同样问题,总不能opencv带vector的接口全部改一遍。
所以,我断定不是编译问题,更不是代码问题,只能是编译方法的问题(STL)。注意到,我的android studio中jni用的-DANDROID_STL=c++_shared,而在编译opencv时,使用gnustl_static.

下面尝试改用c++_shared来编译(经过多次编译实验成功了)
首先,在网上查相关资料:

  1. opencv3及以下的版本仅仅支持gnustl_shared编译
  2. NDK16之后就不支持gnustl_shared的编译了,使用libc++作为默认的STL

基于以上两点,我选择opencv3.4.1和NDK r.18b。
imwrite用gnustl_static编出动态库的符号

_ZN2cv7imwriteERKNS_6StringERKNS_11_InputArrayERKSt6vectorIiSaIiEE

imwrite用c++_shared编出动态库的符号

_ZN2cv7imwriteERKNS_6StringERKNS_11_InputArrayERKNSt6__ndk16vectorIiNS6_9allocatorIiEEEE
二者的符号不同。

准备

下载android-sdk

android-sdk
解压
tools 执行 ./android update sdk
选择一个build-tools安装

android-ndk

https://developer.android.google.cn/ndk/downloads
下载android-ndk-r18b-linux-x86_64.zip
生成独立的工具链

./build/tools/make-standalone-toolchain.sh --install-dir=../android-toolchain-r18b/ --toolchain=arm-linux-androideabi

下载opencv源码

git clone bashhttps://github.com/opencv/opencv.git
git show 3.4.1 # commit-id
git reset --hard commit-id
git checkout -b 3.4.1

编译

在opencv根目录创建build.sh文件

#!/bin/bash
NDK_ROOT="/home/q/project/opencv_compile/opt/android-ndk-r18b"

### ABIs setup
ANDROID_ABI_LIST=("arm64-v8a" "armeabi-v7a")

### path setup
SCRIPT=$(readlink -f $0)
WD=`dirname $SCRIPT`
OPENCV_ROOT="${WD}"
N_JOBS=${N_JOBS:-4}

INSTALL_DIR="${WD}/build"
rm -rf "${INSTALL_DIR}"

### Make each ABI target iteratly and sequentially
for i in "${ANDROID_ABI_LIST[@]}"
do
    ANDROID_ABI="${i}"
    echo "Start building ${ANDROID_ABI} version"

    if [ "${ANDROID_ABI}" = "armeabi" ]; then
        API_LEVEL=19
    else
        API_LEVEL=24
    fi

    temp_build_dir="${OPENCV_ROOT}/platforms/build_android_${ANDROID_ABI}"

    ### Remove the build folder first, and create it
    rm -rf "${temp_build_dir}"
    mkdir -p "${temp_build_dir}"
    cd "${temp_build_dir}"

    echo ${INSTALL_DIR}
    cmake \
        -DCMAKE_MAKE_PROGRAM=/usr/bin/make \
        -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
        -DCMAKE_TOOLCHAIN_FILE=${NDK_ROOT}/build/cmake/android.toolchain.cmake \
        -DANDROID_ABI=${ANDROID_ABI} \
        -DANDROID_STL=c++_shared  \
        -DCMAKE_BUILD_TYPE=Release \
        -DANDROID_NATIVE_API_LEVEL=${API_LEVEL} \
        -DCMAKE_BUILD_TYPE=Release \
        -DWITH_FFMPEG=ON \
        -D BUILD_opencv_java=ON \
        -D BUILD_ANDROID_PROJECTS=ON \
        -D WITH_CUDA=OFF \
        -D WITH_MATLAB=OFF \
        -D BUILD_ANDROID_EXAMPLES=OFF \
        -D BUILD_DOCS=OFF \
        -D BUILD_PERF_TESTS=OFF \
        -D BUILD_TESTS=OFF \
        -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \
        -DANDROID_SDK="/home/q/project/3rd-source/android_sdk" \
        ../..

    # Build it
    make -j${N_JOBS}

    # Install it
    make install/strip

    ### Remove temp build folder
    cd "${WD}"
    rm -rf "${temp_build_dir}"
    echo "end building ${ANDROID_ABI} version"
done

运行

cd opencv
chmod u+x build.sh
./build.sh

你可能感兴趣的:(C++)