Android Ndk Linking

NDK - linking a shared library

Only the JNI function itself should be marked as extern "C", like here:

#include <jni.h>
#include <string>
#include <sstream>
#include <get13.h>

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_semko_myapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject asdf) {
get13();
return 1;
}

If you use javah to prepare a MyApplication/jni/native-lib.h for you, it will have

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_semko_myapplication_MainActivity_stringFromJNI(
JNIEnv* env,
jobject asdf);

for you, and in the cpp file, you will

#include "native-lib.h"

and don't need extern "C" at all.

To make sure that your Android.mk is valid for all architectures, consider this change:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libhello
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libhello.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := native-lib
LOCAL_SRC_FILES := native-lib.cpp
LOCAL_SHARED_LIBRARIES := libhello
include $(BUILD_SHARED_LIBRARY)

Update: the important piece is include $(CLEAR_VARS) before LOCAL_MODULE := libhello.

Android NDK - Error Linking Shared library and JNI Wrapper

Instead of using the ndk standalone toolchain, I used the ndk-build on my build machine which then generated the libs file I needed. From there I added the libs file with the contents of:

  1. arm64-v8a
  2. armeabi-v7a
  3. x86
  4. x86_64

Into my Android directory under src>main>jniLibs which then stored all the files and just added the command to my app build.gradle:

sourceSets.main{
jniLibs.srcDir 'src/main/jniLibs'
}

For ndk-build to work properly I had to include the jniWrapper.c file.

Android.mk:

LOCAL_PATH :=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := testing
LOCAL_SRC_FILES := jniWrapper.c \
testLib.c
include $(BUILD_SHARED_LIBRARY)

Application.mk (I was testing with "all" but its unneeded):

APP_PLATFORM := android-23
APP_ABI := all

I know this is a work around solution but for some reason I could not figure out the toolchain to work correctly.

Android NDK error when linking shared C library

I think you misunderstand the cmake syntax. Below is enough for your case.

target_link_libraries(
main
${log-lib})

Below are source files, NOT library names.

communication_api
cybtldr_api
cybtldr_parse
cybtldr_command

So, you cmake statements are not correct.

If you want to make less confusing, try to make below changes.

find_library( # Sets the name of the path variable.
log-lib
log)

add_library( # Specifies the name of the library.
my-native-lib SHARED
main.c
communication_api.c
cybtldr_api.c
cybtldr_parse.c
cybtldr_command.c
)
target_link_libraries(my-native-lib
${log-lib})

But, remember to change your Java side as well, see below example:

// Used to load the 'my-native-lib' library on application startup.
static {
System.loadLibrary("my-native-lib");
}

I just enclose my JniExample project in case you need: https://github.com/russell-shizhen/JniExample

How to link Android NDK shared library?

I found a way to link. If I make a directory named jniLibs inside app/src/main and then copy all the share library in side. It is able to link and load library. Note that directory name "jniLibs" is case sensitive.

You must call this in source code:-

static{
System.loadLibrary("libray_name"); // without prefix 'lib' and suffix '.so' i.e. "libLibName.so" should be only LibName.
}

Linking VTK with ndk-build on NDK r17c results with 'undefined references' errors

I ended up using CMake insted of ndk-build.

I needed to add this code to my module's build.gradle:

android {
...

defaultConfig {
...

externalNativeBuild {
cmake {
cppFlags "-std=c++11"
arguments "-DANDROID_CPP_FEATURES=rtti exceptions",
"-DANDROID_STL=gnustl_shared"
abiFilters 'arm64-v8a'
}
}
}

...

externalNativeBuild {
cmake {
path "src/main/jni/CMakeLists.txt"
}
}
}

And, my CMakeLists.txt looks like this:

cmake_minimum_required(VERSION 3.4.1)

set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib/${ANDROID_ABI})

add_library(vtk-common-color STATIC IMPORTED)
set_target_properties(vtk-common-color
PROPERTIES IMPORTED_LOCATION
${LIB_DIR}/libvtkCommonColor-8.90.a)

#53 more libraries

add_library( vtk-lib SHARED ${PROJECT_SOURCE_DIR}/vtk-lib.cpp)

target_include_directories(vtk-lib PRIVATE ${PROJECT_SOURCE_DIR}/include)

target_link_libraries(
vtk-lib
-Wl,--start-group -L ${TARGET_OUT}
vtk-common-color
#53 more libraries names
-Wl,--end-group
)

Android: Linking to prebuilt static libraries

Your libraries are interdependent:

Lapack requires Blas
Mumps requires Blas and Metis
Ipopt requires Mumps, Metis, and Lapack

This means that the order for linking them should be reverse:

ipopt
mumps
metis
lapack
blas

If you don't want to waste your time on figuring out the best order, but rather let the linker to find out (this may slow your builds significantly), you can use

target_link_libraries(native-lib -Wl,--start-group
blas
lapack
metis
mumps
ipopt
-Wl,--end-group).

You can also teach CMake about the dependencies between imported static libs, via IMPORTED_LINK_INTERFACE_LIBRARIES, e.g.

set_target_properties(lapack 
PROPERTIES IMPORTED_LINK_INTERFACE_LIBRARIES
blas)

and so on.

This will translate

target_link_libraries( native-lib
blas
lapack
)

To

clang++ -o libnative-lib.so … libblas.a libnlapack.a libblas.a

Android NDK/JNI -- shared library incompatible with armelf_linux_eabi

The linker error suggests that you are building myproject for a different ABI than the one that libmylib.so was built for.

You can tell Gradle to only build your native code for one or more specific ABI(s) by adding an ABI filter:

android {
defaultConfig {
ndk {
abiFilters 'arm64-v8a'
}
}
... other stuff ...
}


Related Topics



Leave a reply



Submit