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

本文主要是介绍error: undefined reference to ‘cv::Mat::~Mat()‘解决AndroidStudio集成OpenVC出现的编译报错问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

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

集成OpenVC静态库

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

  •  小小情意的​ Android 接入 OpenCV库的三种方式 ​
  •  春末的南方城市的在Android端集成OpenCV的三种方式

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

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html# Sets the minimum version of CMake required to build the native library.cmake_minimum_required(VERSION 3.18.1)# Declares and names the project.project("opencv_mobile")include_directories(include)# 设置Debug编译模式,这样才能生成符号表,方便使用addr2line来定位内存地址对应代码行
set(CMAKE_BUILD_TYPE DEBUG)# 设置变量
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -frtti -fexceptions -fopenmp -static-openmp")
set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/opencv/sdk/native/jni)
find_package(OpenCV 4.5.4 REQUIRED core features2d highgui imgproc photo video)
message("OpenCV_FOUND is ${OpenCV_FOUND}")
message("OpenCV_LIBS is ${OpenCV_LIBS}")# 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.opencv_mobile# Sets the library as a shared library.SHARED# Provides a relative path to your source file(s).opencv_mobile.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.opencv_mobile${OpenCV_LIBS}# Links the target library to the log library# included in the NDK.android${log-lib})

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

# ===================================================================================
#  The OpenCV CMake configuration file
#
#             ** File generated automatically, do not modify **
#
#  Usage from an external project:
#    In your CMakeLists.txt, add these lines:
#
#    find_package(OpenCV REQUIRED)
#    include_directories(${OpenCV_INCLUDE_DIRS}) # Not needed for CMake >= 2.8.11
#    target_link_libraries(MY_TARGET_NAME ${OpenCV_LIBS})
#
#    Or you can search for specific OpenCV modules:
#
#    find_package(OpenCV REQUIRED core videoio)
#
#    If the module is found then OPENCV_<MODULE>_FOUND is set to TRUE.
#
#    This file will define the following variables:
#      - OpenCV_LIBS                     : The list of all imported targets for OpenCV modules.
#      - OpenCV_INCLUDE_DIRS             : The OpenCV include directories.
#      - OpenCV_ANDROID_NATIVE_API_LEVEL : Minimum required level of Android API.
#      - OpenCV_VERSION                  : The version of this OpenCV build: "4.5.4"
#      - OpenCV_VERSION_MAJOR            : Major version part of OpenCV_VERSION: "4"
#      - OpenCV_VERSION_MINOR            : Minor version part of OpenCV_VERSION: "5"
#      - OpenCV_VERSION_PATCH            : Patch version part of OpenCV_VERSION: "4"
#      - OpenCV_VERSION_STATUS           : Development status of this build: ""
#
# ===================================================================================

代码结构如下:

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

编译遇到的问题

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

FAILURE: Build completed with 2 failures.1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':OpenCVMobile:buildCMakeDebug[armeabi-v7a]'.
> Build command failed.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}ninja: Entering directory `/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/.cxx/Debug/4r2c6mo1/armeabi-v7a'[1/1] Linking CXX shared library /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/build/intermediates/cxx/Debug/4r2c6mo1/obj/armeabi-v7a/libopencv_mobile.soFAILED: /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/build/intermediates/cxx/Debug/4r2c6mo1/obj/armeabi-v7a/libopencv_mobile.so : && /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 && :/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)'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:24: error: undefined reference to 'cv::Mat::Mat()'/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)'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:53: error: undefined reference to 'cv::Mat::release()'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:54: error: undefined reference to 'cv::Mat::release()'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'clang++: error: linker command failed with exit code 1 (use -v to see invocation)ninja: build stopped: subcommand failed.* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
==============================================================================2: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':OpenCVMobile:buildCMakeRelWithDebInfo[armeabi-v7a]'.
> Build command failed.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}ninja: Entering directory `/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/.cxx/RelWithDebInfo/442v101w/armeabi-v7a'[1/1] Linking CXX shared library /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/build/intermediates/cxx/RelWithDebInfo/442v101w/obj/armeabi-v7a/libopencv_mobile.soFAILED: /work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/build/intermediates/cxx/RelWithDebInfo/442v101w/obj/armeabi-v7a/libopencv_mobile.so : && /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 && :/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)'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:24: error: undefined reference to 'cv::Mat::Mat()'/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)'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:53: error: undefined reference to 'cv::Mat::release()'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:54: error: undefined reference to 'cv::Mat::release()'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'/work/AndroidStudioProjects/AndroidDevelopmentPractices/AndroidJetpackComposeSample/OpenCVMobile/src/main/cpp/opencv_mobile.cpp:55: error: undefined reference to 'cv::Mat::~Mat()'clang++: error: linker command failed with exit code 1 (use -v to see invocation)ninja: build stopped: subcommand failed.* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
==============================================================================* Get more help at https://help.gradle.orgBUILD FAILED in 2s
72 actionable tasks: 4 executed, 68 up-to-date

对应的源码如下:

#include <jni.h>
#include <string>
#include "common.h"
#include <android/bitmap.h>
// for native window JNI
#include <android/native_window_jni.h>
#include <android/native_window.h>
// for native OpenCV JNI
#include "opencv2/core/core.hpp"
#include "opencv2/core/mat.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"using namespace cv;extern "C"
JNIEXPORT void JNICALL
Java_com_nxg_opencv_OpenCVMobile_renderYuvDataOnSurface(JNIEnv *env, jclass clazz, jint width,jint height, jbyteArray yuv_data,jobject surface) {// yuv转rgbajbyte *data = env->GetByteArrayElements(yuv_data, nullptr);cv::Mat yuvImg(height + height / 2, width, CV_8UC1, data);cv::Mat rgbImg;cv::cvtColor(yuvImg, rgbImg, COLOR_YUV2RGBA_IYUV);// 这两行代码用于翻转的,用不到,这里注释掉//cv::transpose(yuvImg, rgbImg);//cv::flip(yuvImg, rgbImg, 1);//获取ANativeWindowANativeWindow *window = ANativeWindow_fromSurface(env, surface);ANativeWindow_acquire(window);//设置ANativeWindow相关参数,包括宽/高/像素格式ANativeWindow_setBuffersGeometry(window, rgbImg.cols, rgbImg.rows, WINDOW_FORMAT_RGBA_8888);ANativeWindow_Buffer outBuffer;// 调用ANativeWindow_lock锁定后台的缓冲部分,并获取surface缓冲区的地址if (int32_t err = ANativeWindow_lock(window, &outBuffer, nullptr)) {LOGE("ANativeWindow_lock failed with error code: %d\n", err);ANativeWindow_release(window);}// 拷贝rgb数据到缓冲区auto *outPtr = reinterpret_cast<uint8_t *>(outBuffer.bits);int dst_line_size = outBuffer.stride * 4;//一行一行拷贝for (int i = 0; i < outBuffer.height; ++i) {//从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中memcpy(outPtr + i * dst_line_size, rgbImg.data + i * rgbImg.cols * 4, dst_line_size);}//绘制ANativeWindow_unlockAndPost(window);//用完释放ANativeWindow_release(window);env->ReleaseByteArrayElements(yuv_data, data, 0);yuvImg.release();rgbImg.release();
}

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

set(OpenCV_DIR ${CMAKE_SOURCE_DIR}/opencv/sdk/native/jni)
find_package(OpenCV 4.5.4 REQUIRED core features2d highgui imgproc photo video)
message("OpenCV_DIR is ${OpenCV_DIR}")
message("OpenCV_FOUND is ${OpenCV_FOUND}")
message("OpenCV_LIBS is ${OpenCV_LIBS}")
target_link_libraries( # Specifies the target library.opencv_mobile${OpenCV_LIBS}# Links the target library to the log library# included in the NDK.android${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一样的版本,并重新编译即可。

android {compileSdk = BuildConfig.compileSdkdefaultConfig {minSdk = 24targetSdk = BuildConfig.targetSdkVersiontestInstrumentationRunner = BuildConfig.testInstrumentationRunnerconsumerProguardFiles("consumer-rules.pro")}
}

修改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这么要求是有它的道理的。

这篇关于error: undefined reference to ‘cv::Mat::~Mat()‘解决AndroidStudio集成OpenVC出现的编译报错问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/195666

相关文章

Nginx 配置跨域的实现及常见问题解决

《Nginx配置跨域的实现及常见问题解决》本文主要介绍了Nginx配置跨域的实现及常见问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来... 目录1. 跨域1.1 同源策略1.2 跨域资源共享(CORS)2. Nginx 配置跨域的场景2.1

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

qt5cored.dll报错怎么解决? 电脑qt5cored.dll文件丢失修复技巧

《qt5cored.dll报错怎么解决?电脑qt5cored.dll文件丢失修复技巧》在进行软件安装或运行程序时,有时会遇到由于找不到qt5core.dll,无法继续执行代码,这个问题可能是由于该文... 遇到qt5cored.dll文件错误时,可能会导致基于 Qt 开发的应用程序无法正常运行或启动。这种错

SpringBoot排查和解决JSON解析错误(400 Bad Request)的方法

《SpringBoot排查和解决JSON解析错误(400BadRequest)的方法》在开发SpringBootRESTfulAPI时,客户端与服务端的数据交互通常使用JSON格式,然而,JSON... 目录问题背景1. 问题描述2. 错误分析解决方案1. 手动重新输入jsON2. 使用工具清理JSON3.

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte

MySQL 设置AUTO_INCREMENT 无效的问题解决

《MySQL设置AUTO_INCREMENT无效的问题解决》本文主要介绍了MySQL设置AUTO_INCREMENT无效的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录快速设置mysql的auto_increment参数一、修改 AUTO_INCREMENT 的值。

关于跨域无效的问题及解决(java后端方案)

《关于跨域无效的问题及解决(java后端方案)》:本文主要介绍关于跨域无效的问题及解决(java后端方案),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录通用后端跨域方法1、@CrossOrigin 注解2、springboot2.0 实现WebMvcConfig

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Java死锁问题解决方案及示例详解

《Java死锁问题解决方案及示例详解》死锁是指两个或多个线程因争夺资源而相互等待,导致所有线程都无法继续执行的一种状态,本文给大家详细介绍了Java死锁问题解决方案详解及实践样例,需要的朋友可以参考下... 目录1、简述死锁的四个必要条件:2、死锁示例代码3、如何检测死锁?3.1 使用 jstack3.2

解决JSONField、JsonProperty不生效的问题

《解决JSONField、JsonProperty不生效的问题》:本文主要介绍解决JSONField、JsonProperty不生效的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录jsONField、JsonProperty不生效javascript问题排查总结JSONField