当前位置:   article > 正文

error: undefined reference to ‘cv::Mat::~Mat()‘解决AndroidStudio集成OpenVC出现的编译报错问题_undefined reference to `cv::mat::mat()

undefined reference to `cv::mat::mat()

前言

本来这种类型的博客不是笔者想写的,不过这个问题,笔者经过网上一番搜索却没有可用的解决方案,因此分享出来帮助大家填坑。

集成OpenVC静态库

OpenCV官方的Android SDK在这里下载,集成方法就不多介绍了,可以看这两位博主的文章:

CMakeList.txt完整配置文件如下:

  1. # For more information about using CMake with Android Studio, read the
  2. # documentation: https://d.android.com/studio/projects/add-native-code.html
  3. # Sets the minimum version of CMake required to build the native library.
  4. cmake_minimum_required(VERSION 3.18.1)
  5. # Declares and names the project.
  6. project("opencv_mobile")
  7. include_directories(include)
  8. # 设置Debug编译模式,这样才能生成符号表,方便使用addr2line来定位内存地址对应代码行
  9. set(CMAKE_BUILD_TYPE DEBUG)
  10. # 设置变量
  11. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti -fexceptions -fopenmp -static-openmp")
  12. set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/opencv/sdk/native/jni)
  13. find_package(OpenCV 4.5.4 REQUIRED core features2d highgui imgproc photo video)
  14. message("OpenCV_FOUND is ${OpenCV_FOUND}")
  15. message("OpenCV_LIBS is ${OpenCV_LIBS}")
  16. # Creates and names a library, sets it as either STATIC
  17. # or SHARED, and provides the relative paths to its source code.
  18. # You can define multiple libraries, and CMake builds them for you.
  19. # Gradle automatically packages shared libraries with your APK.
  20. add_library( # Sets the name of the library.
  21. opencv_mobile
  22. # Sets the library as a shared library.
  23. SHARED
  24. # Provides a relative path to your source file(s).
  25. opencv_mobile.cpp)
  26. # Searches for a specified prebuilt library and stores the path as a
  27. # variable. Because CMake includes system libraries in the search path by
  28. # default, you only need to specify the name of the public NDK library
  29. # you want to add. CMake verifies that the library exists before
  30. # completing its build.
  31. find_library( # Sets the name of the path variable.
  32. log-lib
  33. # Specifies the name of the NDK library that
  34. # you want CMake to locate.
  35. log)
  36. # Specifies libraries CMake should link to your target library. You
  37. # can link multiple libraries, such as libraries you define in this
  38. # build script, prebuilt third-party libraries, or system libraries.
  39. target_link_libraries( # Specifies the target library.
  40. opencv_mobile
  41. ${OpenCV_LIBS}
  42. # Links the target library to the log library
  43. # included in the NDK.
  44. android
  45. ${log-lib})

官方提供的OpenCVConfig.cmake也告诉了我们怎么集成。

  1. # ===================================================================================
  2. # The OpenCV CMake configuration file
  3. #
  4. # ** File generated automatically, do not modify **
  5. #
  6. # Usage from an external project:
  7. # In your CMakeLists.txt, add these lines:
  8. #
  9. # find_package(OpenCV REQUIRED)
  10. # include_directories(${OpenCV_INCLUDE_DIRS}) # Not needed for CMake >= 2.8.11
  11. # target_link_libraries(MY_TARGET_NAME ${OpenCV_LIBS})
  12. #
  13. # Or you can search for specific OpenCV modules:
  14. #
  15. # find_package(OpenCV REQUIRED core videoio)
  16. #
  17. # If the module is found then OPENCV_<MODULE>_FOUND is set to TRUE.
  18. #
  19. # This file will define the following variables:
  20. # - OpenCV_LIBS : The list of all imported targets for OpenCV modules.
  21. # - OpenCV_INCLUDE_DIRS : The OpenCV include directories.
  22. # - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API.
  23. # - OpenCV_VERSION : The version of this OpenCV build: "4.5.4"
  24. # - OpenCV_VERSION_MAJOR : Major version part of OpenCV_VERSION: "4"
  25. # - OpenCV_VERSION_MINOR : Minor version part of OpenCV_VERSION: "5"
  26. # - OpenCV_VERSION_PATCH : Patch version part of OpenCV_VERSION: "4"
  27. # - OpenCV_VERSION_STATUS : Development status of this build: ""
  28. #
  29. # ===================================================================================

代码结构如下:

 源码在这里查看:https://github.com/xiangang/AndroidDevelopmentPractices/tree/develop

编译遇到的问题

集成OpenCV虽然很简单,但有时候也需要一点点运气。像笔者运气就不太好,下面是编译报错的完整日志。

  1. FAILURE: Build completed with 2 failures.
  2. 1: Task failed with an exception.
  3. -----------
  4. * What went wrong:
  5. Execution failed for task ':OpenCVMobile:buildCMakeDebug[armeabi-v7a]'.
  6. > Build command failed.
  7. Error while executing process /home/xiangang/Android/Sdk/cmake/3.18.1/bin/ninja with arguments {-C /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/.cxx/Debug/4r2c6mo1/armeabi-v7a opencv_mobile}
  8. ninja: Entering directory `/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/.cxx/Debug/4r2c6mo1/armeabi-v7a'
  9. [1/1] Linking CXX shared library /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/build/intermediates/cxx/Debug/4r2c6mo1/obj/armeabi-v7a/libopencv_mobile.so
  10. FAILED: /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/build/intermediates/cxx/Debug/4r2c6mo1/obj/armeabi-v7a/libopencv_mobile.so
  11. : && /work/android/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=armv7-none-linux-androideabi23 --gcc-toolchain=/work/android/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/work/android/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -frtti -fexceptions -fopenmp -static-openmp -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--exclude-libs,libunwind.a -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libopencv_mobile.so -o /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/build/intermediates/cxx/Debug/4r2c6mo1/obj/armeabi-v7a/libopencv_mobile.so CMakeFiles/opencv_mobile.dir/opencv_mobile.cpp.o -landroid /work/android/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/23/liblog.so -latomic -lm && :
  12. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:23: error: undefined reference to 'cv::Mat::Mat(int, int, int, void*, unsigned int)'
  13. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:24: error: undefined reference to 'cv::Mat::Mat()'
  14. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:25: error: undefined reference to 'cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int)'
  15. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:53: error: undefined reference to 'cv::Mat::release()'
  16. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:54: error: undefined reference to 'cv::Mat::release()'
  17. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'
  18. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'
  19. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'
  20. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'
  21. clang++: error: linker command failed with exit code 1 (use -v to see invocation)
  22. ninja: build stopped: subcommand failed.
  23. * Try:
  24. > Run with --stacktrace option to get the stack trace.
  25. > Run with --info or --debug option to get more log output.
  26. > Run with --scan to get full insights.
  27. ==============================================================================
  28. 2: Task failed with an exception.
  29. -----------
  30. * What went wrong:
  31. Execution failed for task ':OpenCVMobile:buildCMakeRelWithDebInfo[armeabi-v7a]'.
  32. > Build command failed.
  33. Error while executing process /home/xiangang/Android/Sdk/cmake/3.18.1/bin/ninja with arguments {-C /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/.cxx/RelWithDebInfo/442v101w/armeabi-v7a opencv_mobile}
  34. ninja: Entering directory `/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/.cxx/RelWithDebInfo/442v101w/armeabi-v7a'
  35. [1/1] Linking CXX shared library /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/build/intermediates/cxx/RelWithDebInfo/442v101w/obj/armeabi-v7a/libopencv_mobile.so
  36. FAILED: /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/build/intermediates/cxx/RelWithDebInfo/442v101w/obj/armeabi-v7a/libopencv_mobile.so
  37. : && /work/android/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++ --target=armv7-none-linux-androideabi23 --gcc-toolchain=/work/android/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/work/android/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security -frtti -fexceptions -fopenmp -static-openmp -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--exclude-libs,libunwind.a -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libopencv_mobile.so -o /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/build/intermediates/cxx/RelWithDebInfo/442v101w/obj/armeabi-v7a/libopencv_mobile.so CMakeFiles/opencv_mobile.dir/opencv_mobile.cpp.o -landroid /work/android/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/23/liblog.so -latomic -lm && :
  38. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:23: error: undefined reference to 'cv::Mat::Mat(int, int, int, void*, unsigned int)'
  39. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:24: error: undefined reference to 'cv::Mat::Mat()'
  40. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:25: error: undefined reference to 'cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int)'
  41. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:53: error: undefined reference to 'cv::Mat::release()'
  42. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:54: error: undefined reference to 'cv::Mat::release()'
  43. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'
  44. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'
  45. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'
  46. /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'
  47. clang++: error: linker command failed with exit code 1 (use -v to see invocation)
  48. ninja: build stopped: subcommand failed.
  49. * Try:
  50. > Run with --stacktrace option to get the stack trace.
  51. > Run with --info or --debug option to get more log output.
  52. > Run with --scan to get full insights.
  53. ==============================================================================
  54. * Get more help at https://help.gradle.org
  55. BUILD FAILED in 2s
  56. 72 actionable tasks: 4 executed, 68 up-to-date

对应的源码如下:

  1. #include <jni.h>
  2. #include <string>
  3. #include "common.h"
  4. #include <android/bitmap.h>
  5. // for native window JNI
  6. #include <android/native_window_jni.h>
  7. #include <android/native_window.h>
  8. // for native OpenCV JNI
  9. #include "opencv2/core/core.hpp"
  10. #include "opencv2/core/mat.hpp"
  11. #include "opencv2/highgui/highgui.hpp"
  12. #include "opencv2/imgproc/imgproc.hpp"
  13. using namespace cv;
  14. extern "C"
  15. JNIEXPORT void JNICALL
  16. Java_com_nxg_opencv_OpenCVMobile_renderYuvDataOnSurface(JNIEnv *env, jclass clazz, jint width,
  17. jint height, jbyteArray yuv_data,
  18. jobject surface) {
  19. // yuv转rgba
  20. jbyte *data = env->GetByteArrayElements(yuv_data, nullptr);
  21. cv::Mat yuvImg(height + height / 2, width, CV_8UC1, data);
  22. cv::Mat rgbImg;
  23. cv::cvtColor(yuvImg, rgbImg, COLOR_YUV2RGBA_IYUV);
  24. // 这两行代码用于翻转的,用不到,这里注释掉
  25. //cv::transpose(yuvImg, rgbImg);
  26. //cv::flip(yuvImg, rgbImg, 1);
  27. //获取ANativeWindow
  28. ANativeWindow *window = ANativeWindow_fromSurface(env, surface);
  29. ANativeWindow_acquire(window);
  30. //设置ANativeWindow相关参数,包括宽//像素格式
  31. ANativeWindow_setBuffersGeometry(window, rgbImg.cols, rgbImg.rows, WINDOW_FORMAT_RGBA_8888);
  32. ANativeWindow_Buffer outBuffer;
  33. // 调用ANativeWindow_lock锁定后台的缓冲部分,并获取surface缓冲区的地址
  34. if (int32_t err = ANativeWindow_lock(window, &outBuffer, nullptr)) {
  35. LOGE("ANativeWindow_lock failed with error code: %d\n", err);
  36. ANativeWindow_release(window);
  37. }
  38. // 拷贝rgb数据到缓冲区
  39. auto *outPtr = reinterpret_cast<uint8_t *>(outBuffer.bits);
  40. int dst_line_size = outBuffer.stride * 4;
  41. //一行一行拷贝
  42. for (int i = 0; i < outBuffer.height; ++i) {
  43. //从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
  44. memcpy(outPtr + i * dst_line_size, rgbImg.data + i * rgbImg.cols * 4, dst_line_size);
  45. }
  46. //绘制
  47. ANativeWindow_unlockAndPost(window);
  48. //用完释放
  49. ANativeWindow_release(window);
  50. env->ReleaseByteArrayElements(yuv_data, data, 0);
  51. yuvImg.release();
  52. rgbImg.release();
  53. }

简简单单的代码,怎么就出问题了?检查了头文件,没错。源码,也没错。那就只有一个可能,CMake编译出问题。回过头看集成OpenCV的关键CMake代码:

  1. set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/opencv/sdk/native/jni)
  2. find_package(OpenCV 4.5.4 REQUIRED core features2d highgui imgproc photo video)
  3. message("OpenCV_DIR is ${OpenCV_DIR}")
  4. message("OpenCV_FOUND is ${OpenCV_FOUND}")
  5. message("OpenCV_LIBS is ${OpenCV_LIBS}")
  6. target_link_libraries( # Specifies the target library.
  7. opencv_mobile
  8. ${OpenCV_LIBS}
  9. # Links the target library to the log library
  10. # included in the NDK.
  11. android
  12. ${log-lib})

加了关键变量的打印。最后发现是OpenCV_LIBS变量为空,难怪有问题。

那就看下OpenCVConfig.cmake是在哪里给OpenCV_LIBS赋值的,继续在关键地方加打印如下:

 发现压根没执行到这里。继续往上排查到。最终发现在下图这个红色框部分提前return了。原因是因为编译用的Android版本低于OpenCV_ANDROID_NATIVE_API_LEVEL定义的版本,至此,真相大白!

既然知道原因了,那就好办了。

解决办法

修改minSdkVersion

如果项目没有限制,则直接把对应module的build.gralde的minSdkVersion改为OpenCV_ANDROID_NATIVE_API_LEVEL一样的版本,并重新编译即可。

  1. android {
  2. compileSdk = BuildConfig.compileSdk
  3. defaultConfig {
  4. minSdk = 24
  5. targetSdk = BuildConfig.targetSdkVersion
  6. testInstrumentationRunner = BuildConfig.testInstrumentationRunner
  7. consumerProguardFiles("consumer-rules.pro")
  8. }
  9. }

修改OpenCV_ANDROID_NATIVE_API_LEVEL

你可能会想,我直接改OpenCV_ANDROID_NATIVE_API_LEVEL行不行,比如我项目里是minSdkVersion=23,OpenCV_ANDROID_NATIVE_API_LEVEL的值是24,我直接把OpenCV_ANDROID_NATIVE_API_LEVEL改成23行不行?

笔者实测发现是可以的,但是否有其它未知的问题那就不得而知了。这个方式不是很建议,要相信OpenVC这么要求是有它的道理的。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/300476
推荐阅读
相关标签
  

闽ICP备14008679号