【问题标题】:Android NDK Exception failed: dlopen failed: cannot locate symbol "_ZN7Tangram11setPositionEdd" referenced by "libtangram.so"Android NDK 异常失败:dlopen 失败:找不到“libtangram.so”引用的符号“_ZN7Tangram11setPositionEdd”
【发布时间】:2025-12-06 19:55:01
【问题描述】:

我正在尝试运行一个Library 的演示应用程序,其中集成了android ndk。我在 Android Studio 中导入了this 代码,还下载了 ndk 并将其与项目链接。代码编译并成功构建。它给出了崩溃,异常“初始化时抛出异常 ljava lang unsatisfiedlinkerror”“失败:dlopen 失败:找不到由“libtangram.so”引用的符号“_ZN7Tangram11setPositionEdd”......”

Application.mk:

APP_STL := c++_shared
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi armeabi-v7a x86 mips
APP_PLATFORM := android-19

Android.mk:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := tangram
LOCAL_SRC_FILES := jniExports.cpp jniGenerated.cpp platform_android.cpp
LOCAL_LDLIBS    := -llog
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
include $(BUILD_SHARED_LIBRARY)

模块 Gradle 文件:

buildscript {
  dependencies {
    classpath 'com.android.tools.build:gradle:1.2.3'
    classpath 'com.github.dcendents:android-maven-plugin:1.2'
  }
}

apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'

group = GROUP
version = VERSION_NAME

android {
  compileSdkVersion 22
  buildToolsVersion "21.1.2"

  defaultConfig {
    minSdkVersion 15
    targetSdkVersion 22
 }

   sourceSets.main {
    manifest.srcFile 'AndroidManifest.xml'
    java.srcDirs = ['src']
    jni.srcDirs = []
    assets.srcDirs = ['core/resources']
  }

  task ndkBuild(type: Exec, description: 'Compile JNI source via NDK') {
        commandLine "C:/Users/Administrator/AppData/Local/Android/android-ndk-r10e/ndk-build.cmd",
        'NDK_PROJECT_PATH=build/intermediates/ndk',
        'NDK_LIBS_OUT=jniLibs',
        'APP_BUILD_SCRIPT=jni/Android.mk',
        'NDK_APPLICATION_MK=jni/Application.mk'
  }
  tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
  }
}

// Add gdb server to apk
afterEvaluate {
    Sync packageTask =     project.getTasks().findByName("packageReleaseJniLibs")
        if (packageTask) { packageTask.include(['**/gdbserver',       '**/gdb.setup'])     }

    packageTask = project.getTasks().findByName("packageDebugJniLibs")
    if (packageTask) { packageTask.include(['**/gdbserver', '**/gdb.setup'])         }
    }

dependencies {
  compile 'com.squareup.okhttp:okhttp:2.5.0'
  compile 'xmlpull:xmlpull:1.1.3.1'
}

apply from: file('gradle-mvn-push.gradle')

在 Java 类加载库中:

static {
        System.loadLibrary("c++_shared");
        System.loadLibrary("tangram");
    }

我在谷歌上搜索了这个问题,在这些帖子中Link1Link2Link3Link4 提到它可能是在 api 21 或更高版本上编译并在旧设备上运行它的问题。但是我在我的 Application.mk 中提到了 APP_PLATFORM := android-19 并得到了这个异常。

有什么帮助吗?

【问题讨论】:

  • 请发布您的代码,例如makefile等
  • 我已经看到这个问题出现了几次——一次是因为系统试图使用它自己的库版本(比如在你的 Link2 中),一次是因为我使用的是用NDK 的版本与我的应用程序中的本机代码不同。您是否使用过 nm 工具(包含在 NDK 中)检查符号是否实际由 libtangram.so 导出?这篇文章可能会对您有所帮助:*.com/questions/23044815/…
  • 为什么你的 Android.mk 文件中有LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
  • @odexcide 因为如果我不将它设置为 true,它会给我很多未定义符号的错误
  • @NoumanBhatti 如果您在没有 LOCAL_ALLOW_UNDEFINED_SYMBOLS := true 的情况下看到未定义符号错误,则该符号很可能是未定义符号之一。

标签: android c++ android-ndk java-native-interface


【解决方案1】:

看起来您尝试从自己的自定义 ndk-build 编译 tangram 项目,而不是他们推荐的构建过程 (https://github.com/tangrams/tangram-es#android)。使用他们的构建过程和make 创建 libtangram.so 文件,然后将该 .so 文件复制到您的应用程序的本机库目录中。

它找不到这些符号的原因是因为您在使用 ndk 构建时没有包含定义这些函数的适当源文件。通过忽略未定义的符号,它将编译但无法在运行时解析它们。

您缺少的符号是从 Tangram::setPosition(double, double) 创建的,它在 https://github.com/tangrams/tangram-es/blob/master/core/src/tangram.cpp#L318 中定义;但是,您的 Android.mk 文件不包含该源文件。

【讨论】: