open3d-core-android
open3d-core-android copied to clipboard
C/C++: ld: error: undefined symbol: open3d::io::CreateImageFromFile(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&)
Whenever i try to call CreateImageFromFile (or any other method from this library that receives an std:string as an argument), during compilation i get hit with the following error:
C/C++: ld: error: undefined symbol: open3d::io::CreateImageFromFile(std::__ndk1::basic_string<char, std::__ndk1::char_traits<char>, std::__ndk1::allocator<char> > const&)
I understand that it may be a compilation/ndk problem, but not much more than that.
Here I'll explain how i compiled the project and setup the Android Studio environment:
I am trying to build on Windows 10 I have version 3.14 of CMake installed
I have cloned the project with git clone https://github.com/InstytutXR/open3d-core-android. I have edited the CMakeLists.txt file to download version 0.9.0 instead of 0.10.0 (keeping 0.10 did not work) Inside the downloaded project folder, I have run the commands:
mkdir build & cd build
cmake -G Ninja -DANDROID_NDK=C:\Users\vittorio.veloccia\AppData\Local\Android\Sdk\ndk\20.1.5948944 -DCMAKE_INSTALL_PREFIX=../install .. && cmake --build .
This part correclty builds (aka no errors thrown)
Now i created an Android Studio Native C++ project.
My app's gradle.build file looks like this:
plugins {
id 'com.android.application'
}
android {
namespace 'com.example.testo3d'
compileSdk 33
ndkVersion "20.1.5948944"
defaultConfig {
applicationId "com.example.testo3d"
minSdk 24
targetSdk 33
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
version '3.22.1'
arguments "-DOPEN3D_PATH=C:\\Development\\open3d-core-android\\install"
}
}
ndk {
abiFilters = []
abiFilters.addAll(ABI_FILTERS.split(';').collect{it as String})
}
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
version '3.22.1'
}
}
buildFeatures {
viewBinding true
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
In gradle.properties I have set the following property ABI_FILTERS=armeabi-v7a;arm64-v8a (these 2 are the only ones i have compiled)
My CMakeLists.txt file (inside Android Studio's cpp folder) looks like this:
cmake_minimum_required(VERSION 3.22.1)
project("testo3d")
set(SOURCE_FILES native-lib.cpp)
add_library( ${PROJECT_NAME} SHARED ${SOURCE_FILES})
find_library(log-lib log)
if(NOT OPEN3D_PATH)
message(FATAL_ERROR "Open3D path not specified")
endif()
set(open3d-abi-path ${OPEN3D_PATH}/open3d-${ANDROID_ABI})
find_package(Open3D 0.9.0 # exact match required (major, minor, patch)
REQUIRED
PATHS ${open3d-abi-path}
# don't look anywhere except in the path(s) we specify
NO_DEFAULT_PATH
# ignore the NDK CMAKE_FIND_ROOT_PATH, otherwise all search paths get prefixed with it
NO_CMAKE_FIND_ROOT_PATH)
find_library(open3d-lib
Open3D
PATHS ${Open3D_LIBRARY_DIRS}
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH)
file(COPY ${open3d-lib} DESTINATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI})
# Open3D gives us non-existing directories
# CMake doesn't allow adding those as interface include directories
foreach(dir ${Open3D_INCLUDE_DIRS})
if(NOT EXISTS ${dir})
list(REMOVE_ITEM Open3D_INCLUDE_DIRS ${dir})
endif()
endforeach()
add_library(Open3D SHARED IMPORTED)
set_target_properties(Open3D PROPERTIES
IMPORTED_LOCATION ${open3d-lib})
set_property(TARGET Open3D APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Open3D_INCLUDE_DIRS})
target_link_libraries(# Specifies the target library.
${PROJECT_NAME} PRIVATE
# Links the target library to the log library
# included in the NDK.
${log-lib}
Open3D)
Lastly, my native-lib.cpp file (inside Android Studio's cpp folder) looks like this:
#include <jni.h>
#include "string"
#include "Open3D/Geometry/RGBDImage.h"
#include "Open3D/IO/ClassIO/ImageIO.h"
using namespace open3d::geometry;
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_o3dnative_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string path = "/emulated/storagew/0/Android/data/com.example.testo3d/files/image.jpg";
Image colImg = *open3d::io::CreateImageFromFile(path);
return env->NewStringUTF(path.c_str());
}
Can anyone help me out on understanding what that error might mean and how to resolve it?
I also encountered this problem, and I know why. I used IDA to reversely view the symbol tables of all compiled functions, and found that open3d::io does not exist. Then I found this sentence in the readme: "in this fork IO module is removed since some external libraries are hard to compile (turbojpeg).". The IO code is also commented out in the patch file, so of course IO cannot be used.