[英]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 -landroid
为LOCAL_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_static
到APP_STL := gnustl_shared
在Application.mk
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.