欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Windows编译OpenCV4Android解决undefined reference to std错误

程序员文章站 2023-11-03 23:37:22
OpenCV4Android支持三种使用方式1.Java层调用2.NDK调用动态库(方便,但是会包含整个.so库)3.NDK调用静态库(灵活,比如没有用到机器学习模块,libopencv_ml.a里的代码是不会打包到动态库里的)通过链接静态库的方式使用OpenCV4Android,CMAKE配置如下 ......

opencv4android支持三种使用方式
1.java层调用
2.ndk调用动态库(方便,但是会包含整个.so库)
3.ndk调用静态库(灵活,比如没有用到机器学习模块,libopencv_ml.a里的代码是不会打包到动态库里的)
通过链接静态库的方式使用opencv4android,cmake配置如下

#############################prepare for using of opencv static library####################
#first step to use opencv
set(opencv_static on)
#second step to use opencv
set(opencv_dir c:/sdk/opencv-3.4.2-android-sdk/sdk/native/jni)
#third step to use opencv
find_package(opencv required)
###########################################################################################
##################################################the native-lib shared library############
# creates and names a library, sets it as either static
# or shared, and provides the relative paths to its source code.
# you can define multiple libraries, and cmake builds them for you.
# gradle automatically packages shared libraries with your apk.

add_library( # sets the name of the library.
        native-lib

        # sets the library as a shared library.
        shared

        # provides a relative path to your source file(s).
        src/main/cpp/native-lib.cpp)

# searches for a specified prebuilt library and stores the path as a
# variable. because cmake includes system libraries in the search path by
# default, you only need to specify the name of the public ndk library
# you want to add. cmake verifies that the library exists before
# completing its build.

find_library( # sets the name of the path variable.
        log-lib

        # specifies the name of the ndk library that
        # you want cmake to locate.
        log)

# specifies libraries cmake should link to your target library. you
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # specifies the target library.
        native-lib

        #foutth step to use opencv link opencv
        ${opencv_libs}
        # links the target library to the log library
        # included in the ndk.
        ${log-lib})
######################################################################################

仅仅是新建项目稍稍修改了native-lib.cpp的代码,在函数里用了下opencv的函数

#include <jni.h>
#include <string>
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc_c.h"

extern "c" jniexport jstring jnicall
java_com_example_useprebuiltstaticlibrary_mainactivity_stringfromjni(
        jnienv *env,
        jobject /* this */) {
    std::string hello="hello";
    cv::mat m=cv::mat::eye(3,3,cv_8uc1);
    return env->newstringutf(hello.c_str());
}

编译时却报错

build command failed.
error while executing process c:\sdk\cmake\3.6.4111459\bin\cmake.exe with arguments {--build c:\sdk\demo\useprebuiltstaticlibrary\app\.externalnativebuild\cmake\debug\armeabi-v7a --target native-lib}
[1/2] building cxx object cmakefiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] linking cxx shared library ..\..\..\..\build\intermediates\cmake\debug\obj\armeabi-v7a\libnative-lib.so
failed: cmd.exe /c "cd . && c:\sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe  --target=armv7-none-linux-androideabi23 --gcc-toolchain=c:/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64 --sysroot=c:/sdk/ndk-bundle/sysroot -fpic -isystem c:/sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi -g -dandroid -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -mfpu=neon -wa,--noexecstack -wformat -werror=format-security -std=c++11 -std=c++11 -o0 -fno-limit-debug-info  -wl,--exclude-libs,libgcc.a -wl,--exclude-libs,libatomic.a -nostdlib++ --sysroot c:/sdk/ndk-bundle/platforms/android-23/arch-arm -wl,--build-id -wl,--warn-shared-textrel -wl,--fatal-warnings -wl,--fix-cortex-a8 -wl,--exclude-libs,libunwind.a -lc:/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a -wl,--no-undefined -wl,-z,noexecstack -qunused-arguments -wl,-z,relro -wl,-z,now -shared -wl,-soname,libnative-lib.so -o ..\..\..\..\build\intermediates\cmake\debug\obj\armeabi-v7a\libnative-lib.so cmakefiles/native-lib.dir/src/main/cpp/native-lib.cpp.o  c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_highgui.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_features2d.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_shape.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_imgcodecs.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_ml.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_videoio.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_dnn.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_flann.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_objdetect.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_calib3d.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_video.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_superres.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_photo.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_imgproc.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_stitching.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_videostab.a -llog c:/sdk/opencv-3.4.2-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a/liblibprotobuf.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_calib3d.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_features2d.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_highgui.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_videoio.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_imgcodecs.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a/liblibjpeg-turbo.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a/liblibwebp.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a/liblibpng.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a/liblibtiff.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a/liblibjasper.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a/libilmimf.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_flann.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_video.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_photo.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_imgproc.a c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a -lz c:/sdk/opencv-3.4.2-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a/libtbb.a -lc c:/sdk/opencv-3.4.2-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a/libcpufeatures.a -ldl -lm -llog c:/sdk/opencv-3.4.2-android-sdk/sdk/native/3rdparty/libs/armeabi-v7a/libtegra_hal.a -latomic -lm "c:/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++_static.a" "c:/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++abi.a" "c:/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libunwind.a" "-ldl" && cd ."
c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.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.13]: error: undefined reference to 'std::basic_ios<char, std::char_traits<char> >::clear(std::_ios_iostate)'
c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.cpp:function cv::exception::formatmessage(): error: undefined reference to 'std::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream(std::_ios_openmode)'
c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.cpp:function cv::exception::formatmessage(): error: undefined reference to 'std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)'
c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.cpp:function cv::exception::formatmessage(): error: undefined reference to 'std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)'
c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.cpp:function cv::exception::formatmessage(): error: undefined reference to 'std::ostream::put(char)'
c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.cpp:function cv::exception::formatmessage(): error: undefined reference to 'std::ostream::flush()'
c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.cpp:function cv::exception::formatmessage(): error: undefined reference to 'std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)'
c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.cpp:function cv::exception::formatmessage(): error: undefined reference to 'std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, int)'
c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(system.cpp.o):system.cpp:function cv::exception::formatmessage(): error: undefined reference to 'std::ostream::put(char)'
.
.
.
.
.
.
.
.
.
c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(persistence_json.cpp.o):persistence_json.cpp:function icvjsonparsevalue(cvfilestorage*, char*, cvfilenode*): error: undefined reference to 'std::string::at(unsigned int)' c:/sdk/opencv-3.4.2-android-sdk/sdk/native/staticlibs/armeabi-v7a/libopencv_core.a(persistence.cpp.o):persistence.cpp:function check_if_write_struct_is_delayed(cvfilestorage*, bool): error: undefined reference to 'std::string::assign(char const*, unsigned int)' clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed.

google得知是因为编译这些静态库时所用的编译器、标准库等跟ndk当前的版本不同。网上的建议都是stl改为gnustl_static或gnustl_shared之类。可较新的ndk都不支持这些stl了,为了使用opencv静态库只能重新编译了。
编译opencv4android的过程里爬了不少坑,总结一下,希望有助于小白们。

1. 安装mingw
这里不详细的说了,网上很多教程。选择如图三项安装

Windows编译OpenCV4Android解决undefined reference to std错误

安装好后差不多二三百兆,在环境变量path里添加
c:\mingw\bin
c:\mingw\msys\1.0\bin
这里c:\mingw是我的安装目录。配置好后需要注销计算机,再登陆。在命令行里gcc -v看到能输出版本就算差不多设置好环境了。

2. cmake 配置
下载好源代码解压,我放在c:\opencv-3.4.2。打开cmake图形界面

Windows编译OpenCV4Android解决undefined reference to std错误

如图一定要选择mingw makefiles,我想这也是为什么一定要先安装配置mingw的原因。选择指定工具链,点击next

Windows编译OpenCV4Android解决undefined reference to std错误

这里一定要注意,选择的不是源代码
\opencv-3.4.2\platforms\android\android.toolchain.cmake
这个工具链,这个工具链过时了。新版本的ndk带有自己的工具链,这里选择ndk
/build/cmake/android.toolchain.cmake这个工具链。
这里感谢
https://github.com/opencv/opencv/issues/8742
点击finish。有错误别管,点击configure。开始配置。出现错误就再点configure直到遇到一个跳不过去的错误,看看是不是让你配置sdk路径

android sdk: specify path to android sdk via android_sdk_root /
  android_home / android_sdk variables

点击add entry添加变量

Windows编译OpenCV4Android解决undefined reference to std错误

 注意类型是filepath。点击ok。点击configure。很快又跳出一个错误

cmake error at cmake/android/android_gradle_projects.cmake:1 (message):
  

  android gradle-based build/projects are not supported in this version of
  opencv.

  you need to downgrade android sdk tools to version 25.2.5.

  details: https://github.com/opencv/opencv/issues/8460

call stack (most recent call first):
  cmake/android/opencvdetectandroidsdk.cmake:204 (include)
  cmakelists.txt:645 (include)

这是sdk比较新,新的sdk只支持gradle编译,而opencv需要ant编译。这里也给出了解决方法
details: https://github.com/opencv/opencv/issues/8460
就是下载一个较旧的sdk。正如连接所说,windows选择这个
https://dl.google.com/android/repository/tools_r25.2.5-windows.zip
解压后发现里面只有一个tool目录,而sdk里也有一个tool目录。我的做法是先重命名sdk里的tool为tool28。再将下载的tool复制进sdk。
点击configure。(这里可能还是这个错误,这样就需要删除c:\opencv-3.4.2\build里所有内容,重启cmake。再来一次。所以这一步最好在cmake前就做好。
接下来会遇到这个错误

cmake error at cmake/android/opencvdetectandroidsdk.cmake:184 (message):
  android sdk: can't build android projects as requested by
  build_android_projects=on variable.

  use build_android_projects=off to prepare android project files without
  building them
call stack (most recent call first):
  cmakelists.txt:645 (include)

Windows编译OpenCV4Android解决undefined reference to std错误

如图搜索这个变量,取消选择。点击configure。
配置成功。

Windows编译OpenCV4Android解决undefined reference to std错误

如图搜做tbb选择两项,否则不生成libtbb.a库,我不知这又什么用,但是预编译的sdk里有这个。
还有其它的一些变量可以配置,比如添加android_abi,否则仅仅生成armeabi-v7a。修改变量、添加变量后记得configure。
配置完成点击generate,生成完成。cmake可关闭了。

3.编译
命令行进入c:\opencv-3.4.2\build目录,这里有很多配置好的文件,输入mingw32-make,就开始编译。等好久就成功了。

c:\opencv-3.4.2\build>mingw32-make
scanning dependencies of target gen-pkgconfig
[  0%] generate opencv.pc
[  0%] built target gen-pkgconfig
scanning dependencies of target libcpufeatures
[  0%] building c object 3rdparty/cpufeatures/cmakefiles/libcpufeatures.dir/cpu-features.c.o
[  0%] linking c static library ..\lib\armeabi-v7a\libcpufeatures.a
[  0%] built target libcpufeatures
scanning dependencies of target libjpeg-turbo
[  0%] building c object 3rdparty/libjpeg-turbo/cmakefiles/libjpeg-turbo.dir/src/jcapimin.c.o
[  1%] building c object 3rdparty/libjpeg-turbo/cmakefiles/libjpeg-turbo.dir/src/jcapistd.c.o
[  1%] building c object 3rdparty/libjpeg-turbo/cmakefiles/libjpeg-turbo.dir/src/jccoefct.c.o
[  1%] building c object 3rdparty/libjpeg-turbo/cmakefiles/libjpeg-turbo.dir/src/jccolor.c.o
[  1%] building c object 3rdparty/libjpeg-turbo/cmakefiles/libjpeg-turbo.dir/src/jcdctmgr.c.o
[  1%] building c object 3rdparty/libjpeg-turbo/cmakefiles/libjpeg-turbo.dir/src/jchuff.c.o
[  1%] building c object 3rdparty/libjpeg-turbo/cmakefiles/libjpeg-turbo.dir/src/jcinit.c.o
[  1%] building c object 3rdparty/libjpeg-turbo/cmakefiles/libjpeg-turbo.dir/src/jcmainct.c.o
[  1%] building c object 3rdparty/libjpeg-turbo/cmakefiles/libjpeg-turbo.dir/src/jcmarker.c.o
[  1%] building c object 3rdparty/libjpeg-turbo/cmakefiles/libjpeg-turbo.dir/src/jcmaster.c.o
.
.
.
.
.
.
.
.
.
[ 99%] linking cxx executable ..\..\bin\opencv_perf_stitching
[ 99%] built target opencv_perf_stitching
scanning dependencies of target opencv_videostab
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/deblurring.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/fast_marching.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/frame_source.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/global_motion.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/inpainting.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/log.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/motion_stabilizing.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/optical_flow.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/outlier_rejection.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/stabilizer.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_videostab.dir/src/wobble_suppression.cpp.o
[100%] linking cxx static library ..\..\lib\armeabi-v7a\libopencv_videostab.a
[100%] built target opencv_videostab
scanning dependencies of target opencv_test_videostab
[100%] building cxx object modules/videostab/cmakefiles/opencv_test_videostab.dir/test/test_main.cpp.o
[100%] building cxx object modules/videostab/cmakefiles/opencv_test_videostab.dir/test/test_motion_estimation.cpp.o
[100%] linking cxx executable ..\..\bin\opencv_test_videostab
[100%] built target opencv_test_videostab

4.配置库
生成的库在
\opencv-3.4.2\build\lib
第三方库在
\opencv-3.4.2\build\3rdparty\lib
将其复制到
\opencv-3.4.2-android-sdk
相应目录下替换掉原来的

现在编译项目则没有链接错误了。

参考文章:
1.https://github.com/opencv/opencv/issues/8742
2.https://github.com/opencv/opencv/issues/8460
3.https://blog.csdn.net/xiao19950820/article/details/77119891