Structure Core Depth Camera Android App UnsatisfiedLinkError: cannot locate symbol "__sfp_handle_exceptions"

Structure Core Depth Camera Android App UnsatisfiedLinkError: cannot locate symbol "__sfp_handle_exceptions"

我正在尝试为深度相机 Structure Core 创建一个 android 应用程序。该产品附带 Android API,但问题是 api 文档非常简短且帮助不大。它有一个 APK 文件形式的预构建 Android 应用程序,以及 Windows、Linux 和 Android 的示例项目代码。问题是示例 Android 项目很旧。我设法构建它并安装到设备上,但该应用程序无法启动并出现错误 java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__sfp_handle_exceptions"。 因此,我尝试从头开始制作我的一个非常简单的应用程序,但最后不断弹出相同的错误(应用程序构建并安装成功):

2021-11-30 10:48:02.844 25827-25827/com.bridgewiz.structurecore.coreandroidtrial E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.bridgewiz.structurecore.coreandroidtrial, PID: 25827
    java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__sfp_handle_exceptions" referenced by "/data/app/com.bridgewiz.structurecore.coreandroidtrial-sHH5hFqRXfZv5IT1fQYgmg==/base.apk!/lib/arm64-v8a/libStructure.so"...

API 包含名为 libStructure.so 的核心库 .so 文件和不同示例项目(libDepthTester.solibPlayground.so 等)的实用程序库。

我的问题是,上面给出的错误是由于我的实现方面的问题造成的,还是在编译生产者提供的库 .so 文件时缺少某些内容?

.so文件的入口信息(aarch64-linux-android-readelf.exe)为

在我自己的项目中,app级gradle文件如下:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdk 31

    defaultConfig {
        applicationId "com.bridgewiz.structurecore.coreandroidtrial"
        minSdk 27
        targetSdk 31
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                arguments '-DANDROID_STL=c++_shared'
                targets 'coreandroidtrial'
                abiFilters 'arm64-v8a'
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
    externalNativeBuild {
        cmake {
            path file('CMakeLists.txt')
            version '3.10.2'
        }
    }
    buildFeatures {
        viewBinding true
    }
    sourceSets {
        main {
            jniLibs.srcDirs += ['libs']
        }
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

对应的CMAKELists.txt文件为:


cmake_minimum_required(VERSION 3.10.2)

project("coreandroidtrial")

add_library( # Sets the name of the library.
        coreandroidtrial

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        src/main/cpp/native-lib.cpp)

set_target_properties(coreandroidtrial PROPERTIES LINK_FLAGS "-Wl,-rpath,'$ORIGIN'")

find_library(
        log-lib

        log)


target_link_libraries( # Specifies the target library.
        coreandroidtrial PRIVATE
        ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI}/libDepthTester.so
        ${log-lib})

根据文档,需要的 AppInterface.h 本机文件如下:

#pragma once

/** These functions define the interface between cross-platform sample
    application code and platform-specific wrappers. */
namespace AppInterface {
    /** On desktop platforms this function is called in main() before
        runUntilWindowClosed(). On Android it is called when the main activity
        is created. */
    void setup();

    /** On desktop platforms this function is called in main() after
        runUntilWindowClosed(). On Android it is called when the main activity
        is destroyed. */
    void teardown();

    /** See Window::renderFrameInGLSurfaceViewContext(). */
    void renderFrame(unsigned currentWidth, unsigned currentHeight, float scaleFactor);

    /** See Window::updateMouseState(). */
    void updateMouseState(bool down, int x, int y);

    /** For applications that require Structure Core USB support. The argument
        is a file descriptor from the Android UsbDeviceConnection API and should
        be passed to ST::registerSensorByUSBFileDescriptor() or equivalent. */
    void plugStructureCoreFileDescriptor(int fd);


    /** For applications requiring CLI command support, this function will be processed before getting any GUI level setup*/
    void cliCmdHandler(int argc, char **argv);
}

在我的默认 native-lib.cpp 文件中,只有 JNIEXPORT 函数定义及其对 ApplicationInterface 的各自调用:

#include <jni.h>
#include <string>
#include <thread>

#include "AppInterface.h"


extern "C" JNIEXPORT jstring JNICALL
Java_com_bridgewiz_structurecore_coreandroidtrial_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++ v4";
    return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT void JNICALL
Java_com_bridgewiz_structurecore_coreandroidtrial_MainActivity_setupApp(JNIEnv *env, jobject thiz) {
    AppInterface::setup();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_bridgewiz_structurecore_coreandroidtrial_MainActivity_teardownApp(JNIEnv *env,
                                                                           jobject thiz) {
    AppInterface::teardown();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_bridgewiz_structurecore_coreandroidtrial_MainActivity_renderFrame(JNIEnv *env,
                                                                           jobject thiz,
                                                                           jint current_width,
                                                                           jint current_height,
                                                                           jfloat scale_factor) {
    AppInterface::renderFrame((unsigned)current_width, (unsigned)current_height, scale_factor);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_bridgewiz_structurecore_coreandroidtrial_MainActivity_updateMouseState(JNIEnv *env,
                                                                                jobject thiz,
                                                                                jboolean down,
                                                                                jint x, jint y) {
    AppInterface::updateMouseState(down, x, y);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_bridgewiz_structurecore_coreandroidtrial_MainActivity_plugStructureCoreFileDescriptor(
        JNIEnv *env, jobject thiz, jint fd) {
    AppInterface::plugStructureCoreFileDescriptor(fd);
}

您可能会看到项目文件和文件夹结构

通过一些搜索,看起来 __sfp_handle_exceptionslibstdc++(来自 GCC)的一部分,而现代 Android NDK 附带 libc++ (Clang)。 最好的办法是向供应商索要针对 libc++.

编译的库

如果他们不能或不会提供这样的东西,您可以尝试存根该函数或复制其实现 from here,但我不知道后者是否允许在许可方面使用。即便如此,也不能保证您最终会得到一个可用的应用程序。