简体   繁体   English

使用Android NDK构建本机OpenCV提供了“对'cv :: String :: deallocate()的未定义引用”

[英]Building native OpenCV using Android NDK gives “undefined reference to 'cv::String::deallocate()'”

I'm attempting to use OpenCV with the NDK in Android Studio. 我正在尝试将OpenCV与Android Studio中的NDK一起使用。 As you may notice I'm using another native library called GStreamer. 您可能会注意到,我正在使用另一个名为GStreamer的本机库。

My build.gradle: 我的build.gradle:

apply plugin: 'com.android.application'

def getNdkCommandLine(ndkRoot, target) {
    def gstRoot
    def opencvRoot
    gstRoot = 'C:/local/gstreamer-1.0-android-arm-1.8.0'
    opencvRoot = 'C:/local/OpenCV-3.1.0-android-sdk/OpenCV-android-sdk'

    if (ndkRoot == null)
        throw new GradleException('NDK not configured')

    return ["$ndkRoot/ndk-build.cmd",
            'NDK_PROJECT_PATH=build',
            'APP_BUILD_SCRIPT=src/main/jni/Android.mk',
            'NDK_APPLICATION_MK=src/main/jni/Application.mk',
            'GSTREAMER_JAVA_SRC_DIR=src/main/java',
            "GSTREAMER_ROOT_ANDROID=$gstRoot",
            "OPENCV_ROOT_ANDROID=$opencvRoot",
            "$target"]
}

android {
    compileSdkVersion 19
    buildToolsVersion "23.0.2"

    sourceSets {
        main {
            // Avoid using the built in JNI generation plugin
            jni.srcDirs = []
            jniLibs.srcDirs = ['build/libs']
        }
    }

    defaultConfig {
        applicationId "com.mytestcom.mytestapp"
        minSdkVersion 19
        targetSdkVersion 19
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_7
            targetCompatibility JavaVersion.VERSION_1_7
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            signingConfig signingConfigs.release
        }
    }

    // Before compiling our app, prepare NDK code
    tasks.withType(JavaCompile) {
        compileTask -> compileTask.dependsOn ndkBuild
    }

    // Need to call clean on NDK ourselves too
    clean.dependsOn 'ndkClean'

    // Build native code using mk files like on Eclipse
    task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') {
        commandLine getNdkCommandLine(android.ndkDirectory, 'TARGET_ARCH_ABI=armeabi-v7a')
    }

    task ndkClean(type: Exec, description: 'Clean JNI code built via NDK') {
        commandLine getNdkCommandLine(android.ndkDirectory, 'clean')
    }

    //Renames APK to current versionName found in Android Manifest
    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def outputFile = output.outputFile
            if (outputFile != null && outputFile.name.endsWith('.apk')) {
                def fileName = "My_Test_App-${versionName}.apk"
                output.outputFile = new File(outputFile.parent, fileName)
            }
        }
    }
}

dependencies {
    compile 'com.android.support:support-v4:19.1.0'
    compile project(':openCVLibrary310')
}

Android.mk: Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := gstplayer
LOCAL_SRC_FILES := player.cpp
LOCAL_C_INCLUDES := $(OPENCV_ROOT_ANDROID)/sdk/native/jni/include

LOCAL_SHARED_LIBRARIES := gstreamer_android
LOCAL_LDLIBS := -llog -landroid
include $(BUILD_SHARED_LIBRARY)

ifeq ($(TARGET_ARCH_ABI),armeabi)
GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ARM)
else ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ARMV7)
else ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ARM64)
else ifeq ($(TARGET_ARCH_ABI),x86)
GSTREAMER_ROOT        := $(GSTREAMER_ROOT_X86)
else ifeq ($(TARGET_ARCH_ABI),x86_64)
GSTREAMER_ROOT        := $(GSTREAMER_ROOT_X86_64)
else
$(error Target arch ABI not supported)
endif

ifndef GSTREAMER_ROOT
ifndef GSTREAMER_ROOT_ANDROID
$(error GSTREAMER_ROOT_ANDROID is not defined!)
endif
GSTREAMER_ROOT        := $(GSTREAMER_ROOT_ANDROID)
endif

GSTREAMER_NDK_BUILD_PATH  := $(GSTREAMER_ROOT)/share/gst-android/ndk-build/

include $(GSTREAMER_NDK_BUILD_PATH)/plugins.mk
GSTREAMER_PLUGINS         := $(GSTREAMER_PLUGINS_CORE) $(GSTREAMER_PLUGINS_PLAYBACK) $(GSTREAMER_PLUGINS_CODECS) $(GSTREAMER_PLUGINS_NET) $(GSTREAMER_PLUGINS_SYS) $(GSTREAMER_PLUGINS_CODECS_RESTRICTED) $(GSTREAMER_CODECS_GPL) $(GSTREAMER_PLUGINS_ENCODING) $(GSTREAMER_PLUGINS_VIS) $(GSTREAMER_PLUGINS_EFFECTS) $(GSTREAMER_PLUGINS_NET_RESTRICTED)
GSTREAMER_EXTRA_DEPS      := gstreamer-player-1.0 gstreamer-video-1.0 glib-2.0

OPENCV_INSTALL_MODULES:=on
OPENCV_CAMERAMODULES:=off
OPENCV_LIB_TYPE:=STATIC

include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer-1.0.mk
include $(OPENCV_ROOT_ANDROID)/sdk/native/jni/OpenCV.mk

Application.mk: Application.mk:

APP_PLATFORM=android-19
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a

I'm using OpenCV-3.1.0-android-sdk, NDK r10e, Android Studio 2.1, Windows. 我正在使用OpenCV-3.1.0-android-sdk,NDK r10e,Android Studio 2.1,Windows。 I've tried using a different version of OpenCV (2.4.11) but it didn't help. 我尝试使用其他版本的OpenCV(2.4.11),但没有帮助。

C:\local\OpenCV-3.1.0-android-sdk\OpenCV-android-sdk\sdk\native\jni\include\opencv2\core\cvstd.hpp
Error:(625) undefined reference to 'cv::String::allocate(unsigned int)'
Error:(667) undefined reference to 'cv::String::deallocate()'
Error:(667) undefined reference to 'cv::String::deallocate()'
Error:(667) undefined reference to 'cv::String::deallocate()'
Error:(667) undefined reference to 'cv::String::deallocate()'

C:\local\OpenCV-3.1.0-android-sdk\OpenCV-android-sdk\sdk\native\jni\include\opencv2\core\mat.inl.hpp
Error:(443) undefined reference to 'cv::error(int, cv::String const&, char const*, char const*, int)'
Error:(459) undefined reference to 'cv::error(int, cv::String const&, char const*, char const*, int)'
Error:(682) undefined reference to 'cv::Mat::deallocate()'
Error:(571) undefined reference to 'cv::fastFree(void*)'
Error:(592) undefined reference to 'cv::Mat::copySize(cv::Mat const&)'

I ran into a similar issue a few days ago. 几天前,我遇到了类似的问题。 Imo, you should try to replace LOCAL_LDLIBS := -llog -landroid with LOCAL_LDLIBS += -llog -landroid . Imo,您应该尝试将LOCAL_LDLIBS := -llog -landroidLOCAL_LDLIBS += -llog -landroid

The explanation for these errors is that the OpenCV code being used in GStreamer doesn't have access to the rest of the library, so it's failing to find basic methods like allocate() and deallocate() . 这些错误的解释是,GStreamer中使用的OpenCV代码无权访问该库的其余部分,因此无法找到诸如allocate()deallocate()类的基本方法。

The solution was to include some prebuilt static libraries in the Android.mk so that these references are defined. 解决方案是在Android.mk中包含一些预构建的静态库,以便定义这些引用。 So after include $(OPENCV_ROOT_ANDROID)/sdk/native/jni/OpenCV.mk I added these lines to add the relevant libraries: 所以在include $(OPENCV_ROOT_ANDROID)/sdk/native/jni/OpenCV.mk我添加了以下include $(OPENCV_ROOT_ANDROID)/sdk/native/jni/OpenCV.mk行以添加相关的库:

include $(CLEAR_VARS)
LOCAL_MODULE := opencv-tbb
LOCAL_SRC_FILES := opencvLib/3rdparty/libs/$(TARGET_ARCH_ABI)/libtbb.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := opencv-core
LOCAL_SRC_FILES := opencvLib/$(TARGET_ARCH_ABI)/libopencv_core.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/opencvLib/include/
LOCAL_STATIC_LIBRARIES := opencv-tbb
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := opencv-imgproc
LOCAL_SRC_FILES := opencvLib/$(TARGET_ARCH_ABI)/libopencv_imgproc.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/opencvLib/include/
LOCAL_STATIC_LIBRARIES := opencv-core
include $(PREBUILT_STATIC_LIBRARY)

The LOCAL_EXPORT_C_INCLUDES variable sets the include files that correspond to that library. LOCAL_EXPORT_C_INCLUDES变量设置与该库相对应的包含文件。 In this case the include folder works for both libraries. 在这种情况下,include文件夹适用于两个库。

Now for the GStreamer code to be able to use these libraries we have to add LOCAL_STATIC_LIBRARIES := opencv-core opencv-imgproc to the gstplayer module which references the 2 added OpenCV modules. 现在, LOCAL_STATIC_LIBRARIES := opencv-core opencv-imgproc GStreamer代码能够使用这些库,我们必须将LOCAL_STATIC_LIBRARIES := opencv-core opencv-imgproc到gstplayer模块中,该模块引用了两个已添加的OpenCV模块。

Edit: 编辑:

Also I forgot to mention I changed APP_STL := gnustl_static to APP_STL := gnustl_shared in Application.mk 此外,我忘了提我改APP_STL := gnustl_staticAPP_STL := gnustl_shared在Application.mk

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM