Issue
I am trying to create an android application for the depth camera Structure Core. This product comes with an Android API but the problem is that the api documentation is very short and not very helpful. It has one prebuilt Android app in the form of an APK file, and sample project codes for Windows, Linux and Android. The problem is the sample Android project is very old. I managed to build it and install to a device, but the app does not launch with the error java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "__sfp_handle_exceptions"
.
Therefore I tried to make a very simple application of mine from scratch, but in the end the same error keeps popping up (the application builds and installs successfully):
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"...
The API includes the core library .so file named libStructure.so
and utility libraries for different sample projects (libDepthTester.so
,libPlayground.so
etc.).
My question is whether the error given above results from issues on my implementation side or there is something missing in compilation of the library .so files supplied by the producer?
The entry information of the .so files (obtained by aarch64-linux-android-readelf.exe) is
In my own project, the app level gradle file is as follows:
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'
}
The corresponding CMAKELists.txt file is:
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})
Based on the documentation, the needed AppInterface.h
native file is as below:
#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);
}
Inside my default native-lib.cpp
file there is only the JNIEXPORT function definitions with their respective calls to the 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);
}
You may see the project file and folder structure
Solution
From a bit of searching it looks like __sfp_handle_exceptions
is part of libstdc++
(from GCC), while modern Android NDKs ship with libc++
(Clang).
Your best bet is to ask the vendor for a library compiled against libc++
.
If they cannot or will not provide such a thing, you could try stubbing the function or copying its implementation from here, but I do not know if the latter is allowed license-wise. Even so, no guarantees that you will end up with a working app.
Answered By - Botje
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.