2016-07-21 202 views
1

我试图在Android Studio中使用OpenCV与NDK。您可能会注意到我正在使用另一个名为GStreamer的本机库。使用Android NDK构建原生OpenCV给出“未定义的引用''cv :: String :: deallocate()''

我的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:

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:

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

我使用的OpenCV-3.1.0-android- sdk,NDK r10e,Android Studio 2.1,Windows。我试过使用不同版本的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&)' 
+0

改变APP_STL := gnustl_staticAPP_STL := gnustl_shared我相信这个问题是正在使用的.HPP文件需要外部库建成并链接到。例如,** libopencv_core.a **。因此,在[this](https://developer.android.com/ndk/guides/prebuilts.html)链接之后,我添加了一个部分给我的Android.mk文件,该文件应该添加一个模块作为'PREBUILT_STATIC_LIBRARY'。我已经修复了由于这个添加而导致的所有错误,但是我回到了之前的错误(undefined reference to ...) – MarkyDD

+0

这是确定的。我没有看到应用程序链接的库的任何设置。 –

回答

0

对这些错误的解释是GStreamer中使用的OpenCV代码无法访问库的其余部分,因此无法找到像allocate()deallocate()这样的基本方法。

解决方案是在Android.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) 

LOCAL_EXPORT_C_INCLUDES变量将包括对应于该库文件。在这种情况下,include文件夹适用于这两个库。

现在要使GStreamer代码能够使用这些库,我们必须将LOCAL_STATIC_LIBRARIES := opencv-core opencv-imgproc添加到gstplayer模块,该模块引用了2个添加的OpenCV模块。

编辑:

此外,我忘了说我在Application.mk

+0

在OpenCV.mk中,有两个函数:'add_opencv_module'和'add_opencv_3rdparty_component'。它们以opencv_ *的方式生成'LOCAL_MODULE's。例如opencv_core,opencv_imgproce ...我很好奇为什么你没有得到模块名称冲突错误,然后我意识到你使用' - '而不是'_'。所以如果你尝试使用'opencv_ *',你最终可能会删除你定义的所有3个模块:D。 – r0ng

0

几天前我遇到了类似的问题。伊莫,您应该尝试用LOCAL_LDLIBS += -llog -landroid替换LOCAL_LDLIBS := -llog -landroid

相关问题