android ndk UnsatisfiedLinkError when using a prebuilt shared library - android

I'm trying to create a shared library that links to another shared library.
Here is my main module Android.mk:
TOP_LOCAL_PATH := $(call my-dir)
include $(call all-subdir-makefiles)
LOCAL_PATH := $(TOP_LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_CPP_EXTENSION := cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ $(LOCAL_PATH)/lib/include
LOCAL_MODULE := SightCore-jni
LOCAL_SRC_FILES := SightDemo.cpp SightCore-jni.cpp
LOCAL_SHARED_LIBRARIES := SightAPI
LOCAL_LDLIBS = -llog
include $(BUILD_SHARED_LIBRARY)
I also have the prebuilt shared library in ./lib directory with its own Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := SightAPI
LOCAL_SRC_FILES := libSightAPI.so
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
The SightCore-jni.cpp source file is the jni interface to the shared library and is loaded using the command
System.loadLibrary("SightCore-jni");
During the ndk-build process I get no compilation or linkage errors.
When I try to run the application and access one of the native methods I get the UnsatsfiedLinkError.
I noticed that if disable the references to the SightAPI in my jni code and put a typo to the LOCAL_STATIC_LIBRARIES := SightAPI line, The build is successful and there is no UnsatisfiedLinkError.
This mean that the jni code I have is good (I'm actually sure it is ok...)
So the observation is as follows:
If I compile the shared library with the prebuilt shared library I get a corrupted .so file.
If I compile the same ndk project without linking to the prebuilt shared library there is no problem loading the shared library from the java side.
Please help me out if you can.
Thanks in advance,
Ita

Found the issue.
Apparently the ndk build system doesn't automatically load referenced shared libraries, even if they are declared in your Android.mk.
I had to call on System.loadLibrary(SightAPI) & System.loadLibrary("SightCore-jni") in order to solve this issue. I would have expected that the only library to load would have been the main library SightCore-jni.
Well..I guess the moral is If you want something done, do it yourself :)
+1 to Roy Samuel for his effort and correct instincts.
I hope this helps anyone.
Cheers

Have you made sure that the cpp function name, that you'd like to use over JNI, is corresponding to the package name of the Java wrapper class where System.loadLibrary("SightCore-jni"); is present?
e.g. If you would like to use the C function, myFunction in the java layer, and suppose your JNI wrapper class is in the package com.my.package.sightcore,
then your C code function name should be like this :
JNIEXPORT JNICALL Java_com_my_package_sightcore_myFunction(JNIEnv * env, jobject thiz, ...)
If you are running your app on your device,
See if the API levels, and hence, the sdk release matches to your device's android version (API level).
Hope this helps. Let me know if you need more clarifications...

This happened to me, and the solution for me was to make sure I was including the proper file libgnustl_shared.so and not libc++_shared.so after I switched compilers. So, just making sure either one of these files is the correct one for your build, and making sure it's been updated with the latest, you shouldn't get this issue any longer.

Related

Native method not found while using .so File in libs Android

I have .so file which i have created using a c library .Now i want to use .so file in another project for call those functions. I don't know how to use that library. How to call any function from that library? I have tried but found error as Native method not found.I am a beginner with Ndk in android.any help on this..??
I have referred many links those were not solved my problem as
Native method not found,
java.lang.UnsatisfiedLinkError: Native method not found,
I am facing the same as this link but it is unanswered. link is
Need NDK Help: How to call a C++ function for shared library from another project that uses C++
My Android.mk file is as follows from which i have created .so file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ShairportSample
LOCAL_SRC_FILES := ShairportSample.cpp
APP_PLATFORM := android-19
include $(BUILD_SHARED_LIBRARY)
you can call functions implemented inside the .so you want to reuse from another NDK lib, by setting it as prebuilt shared library your're depending on inside your Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ShairportSample
LOCAL_SRC_FILES := libs/$(TARGET_CPU_ABI)/libShairportSample.so
LOCAL_EXPORT_C_INCLUDES := PATH_TO_ShairportSample.h
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := yournewlib
LOCAL_SRC_FILES := yournewlib.cpp
LOCAL_SHARED_LIBRARIES += ShairportSample
include $(BUILD_SHARED_LIBRARY)
From your Java code you'll have to load ShairportSample lib from your Java before loading yournewlib.
Otherwise, if you want to reuse your .so directly from Java, you should export a Java library (.jar) that uses it. Then you can reuse this Java lib from your other project.
first of all, you should make sure the .so file being compiled correctly, named it like this libYourLibName.so, put it into libs/armeabi folder.
secondly, make sure you have loaded the .so file from static block
static {
System.loadLibrary("YourLibName");
}
may this will help you

How to build multiple projects in the correct dependency order with Android NDK?

I have a series of existing libraries which I need to re-use in an Android application. The layout is similar to:
\Libraries\libOne
\Libraries\libTwo [Static library]
\Libraries\libThree
\Applications\MyApplication\ [Application]
libTwo depends on libOne, and libThree depends on libTwo. How can I get the build system to build all of the libraries in the correct order? I'm trying to use Eclipse, but if necessary I can use the command line.
All of these libraries will eventually be referenced by a Java application (and use JNI to interact with them). Any clues on how I setup the Android.mk / Application.mk files?
I've tried using BUILD_STATIC_LIBRARY for libTwo, but it doesn't actually output any files! I was expecting a libTwo.a file, but nothing gets compiled or built.
Do I write one Android.mk in the application? Or an Android.mk for each project?
OK, now I see your edit, and this makes it possible to answer the specific question.
You must have at least one Android.mk file for your application if you want to use Android NDK to build your native library/ies. This is not a requirement, though. It is OK to build it though Cmake, or a "standalone toolchain" with "traditional" makefiles, or with a MS Visual Studio plugin, or any other way. It is the result that matters. The result is a shared object built with a compatible compiler for a bionic runtime.
It makes goode sense to put the library in ${project_root}/libs/armeabi/ directory (for ARM v6 compatible devices, other subdirectories for x86, MIPS, arm v7a) to allow the APK builder pack it correctly, to allow app installer to unpack the correct version (compatible with the device processor) into /data/data/${package_name}/lib directory on the device, and finally to be able to use System.loadLibrary(short_name) to use it from Java. But it is also quite possible to pack the so file differently, unpack it manually, and load it from any place on the device file system (provided your app has permission to write and read this file).
But if we filter out exotic cases, it is much more comfortable to have an Android.mk in the ${project_root}/jni directory. In terms of ndk-build command, each library is a separate MODULE, but all three may be defined in one Android.mk file. On the other hand, if your libraries are isolated (e.g. come from separate 3rd parties), you will probably prefer to create three Android.mk files. Luckily, ndk-build is nothing but a wrapper around gnu make, and the simple include statement in Android.mk works as in any other makefiles.
In summary, your case is probably covered by a simple Applications/MyApplication/ [Application]/jni/Android.mk file:
include ../../Libraries/libOne/Android.mk
include ../../Libraries/libTwo/Android.mk
include ../../Libraries/libThree/Android.mk
I don't know what dependency you have between libOne and libTwo, but for libOne the file Libraries/libOne/Android.mk will look like
LOCAL_PATH = $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libOne
LOCAL_SRC_FILES := first.c
include $(BUILD_STATIC_LIBRARY)
and Libraries/libThree/Android.mk
LOCAL_PATH = $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libThree
LOCAL_SRC_FILES := third.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libOne $(LOCAL_PATH)/../libTwo
LOCAL_STATIC_LIBRARIES := libOne libTwo
include $(BUILD_SHARED_LIBRARY)
You should run ndk-build from Applications/MyApplication/ [Application] directory - either from command prompt, or through Eclipse ADT plugin.
update the same may be expressed by one Android.mk file in jni directory:
LOCAL_PATH = ../../Libraries/libOne
include $(CLEAR_VARS)
LOCAL_MODULE := libOne
LOCAL_SRC_FILES := first.c
include $(BUILD_STATIC_LIBRARY)
LOCAL_PATH = ../../Libraries/libThree
include $(CLEAR_VARS)
LOCAL_MODULE := libThree
LOCAL_SRC_FILES := third.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libOne $(LOCAL_PATH)/../libTwo
LOCAL_STATIC_LIBRARIES := libOne libTwo
include $(BUILD_SHARED_LIBRARY)
There is an android section in the projects' properties, where you can edit the library dependencies. It can only be used, if libOne libTwo and libThree are marked as libraries, in their properties panel.

android NDK, use functions from compiled .so library in another android NDK project

my problem is that, I don't know how to call functions form .so library.
I have successfully compiled NDK library spatialite-android and have no problems to use it in android Java application. But I have no idea how exactly use it in another NDK project. I have added it in Android.mk file:
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-8
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := UsingSpatialite
LOCAL_SRC_FILES := UsingSpatialite.c
LOCAL_LDLIBS := -llog -lGLESv1_CM
include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := /home/spatialite/jni
include $(CLEAR_VARS)
LOCAL_MODULE := libjsqlite
LOCAL_SRC_FILES := libjsqlite/libjsqlite.so
include $(PREBUILT_SHARED_LIBRARY)
And library libjsqlite.so(android-spatialite) is successfully added in: libs/armeabi/libjsqlite.so
From this point, I don't know how to use that library. How to call any function from that library?
From what I understand from question , you have complied a so file and it runs for lets say Project A and its working . Now, you want use it in Project B .
You cannot directly use the compile library in Project B. The issue is your function
signatures inside your code. For different package names the corresponding function signature will change .
JNIEXPORT jint JNICALL Java_com_your_packageA_class_method(JNIEnv *d, jobject e, jstring f)
{
//some action
}
You need a jar which contains classes to make call to native functions with your compiled so file to make it accessible to Project B .
This is how it will work Project B will make a call to jar which will make call to compiled so file and return the result to A .

Re-use code Android NDK

I found a lot of tutorials showing how to start developing Android Applications using NDK.
But I have a rather "easy/stupid" question:
Please consider the following two tutorials:
http://mobile.tutsplus.com/tutorials/android/ndk-tutorial/
http://www.indiedb.com/tutorials/creating-compiling-and-deploying-native-projects-from-the-android-ndk
http://mindtherobot.com/blog/452/android-beginners-ndk-setup-step-by-step/
http://marakana.com/forums/android/examples/49.html
Now, in the second tutorial they are building the hello-jni example.
My question is:
After using the ndk-build
and producting the:
is it possible to use the resulted libhello-jni.so and distribute this to others instead of the actual C code?
For example modifying the Android.mk and replacing com_myproject_MyActivity.c to something.so in order to include the shared library?:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mylib
LOCAL_SRC_FILES := com_myproject_MyActivity.c
include $(BUILD_SHARED_LIBRARY)
Any suggestions or tutorials welcome. Thanks in advance.
You can use a prebuilt NDK library by copying it into libs/armeabi (or whatever architecture is it for), then loading in run-time. From the standpoint of the Android build system, it's just another file to include in the APK.
The problem, however, is that the JNI function names include, by convention, the name of the package and class they will belong to; so from the standpoint of a SO consumer project, its use will look rather unnatural, as none of the JNI functions would fit into its classes. You'll probably have to ship a companion JAR where the respective Java classes are declared.
Via VitamioBundle,
You no need to do re-using code:
is it possible to use the resulted libhello-jni.so and distribute this to others instead of the actual C code? For example modifying the Android.mk and replacing com_myproject_MyActivity.c to something.so in order to include the shared library?
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mylib
LOCAL_SRC_FILES := com_myproject_MyActivity.c
include $(BUILD_SHARED_LIBRARY)
VitamioBundle can be considered as shared library,
Therefore, you can use it as your Android Library.
Let's fun.

Build issue when using prebuilt libraries with the Android NDK

I have a program I am porting that links together multiple libraries when creating the executable. I have built all those libraries using the stand alone toolchain and using the standalone toolchain I am able to create an executable that works on an android device. So, it seems like the libraries I have built are functional. Now I am trying to incorporate those libraries with an app. So, in my android.mk I have something like this:
LOCAL_PATH := $(call my-dir)
ROOT_PATH := $(LOCAL_PATH)
include $(call all-subdir-makefiles)
include $(CLEAR_VARS)
LOCAL_PATH = $(ROOT_PATH)
LOCAL_MODULE := test-libs
LOCAL_STATIC_LIBRARIES := staticA
LOCAL_SHARED_LIBRARIES := sharedA sharedB sharedC sharedD
LOCAL_SRC_FILES := test-libs.c
include $(BUILD_SHARED_LIBRARY)
For each of the libraries, I have a Android.mk like this
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sharedA
LOCAL_SRC_FILES := sharedA.so
include $(PREBUILT_SHARED_LIBRARY)
When I then build my project (in eclipse), I get this:
C:/ndk/android-ndk-r7b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.4.3/libgcc.a(unwind-arm.o): In function `__gnu_unwind_pr_common':
/cygdrive/c/ndk/android-ndk-r7b/build/core/build-binary.mk:314: recipe for target `obj/local/armeabi/libtest-libs.so' failed
/tmp/ndk-digit/src/build/../gcc/gcc-4.4.3/libgcc/../gcc/config/arm/unwind-arm.c:1237: undefined reference to `__cxa_call_unexpected'
Any thoughts on what is going wrong?
Also, the static library and one of the shared libraries have no dependencies on anything and if I only include them all is cool. One of my shared libraries only had a dependency on the static library. If I only include those, but when I include the others, which have dependencies on other shared libraries, this problem occurs.
Update 1: Ok it appears to be because the APP_STL setting in my Application.mk was being ignored. All I have in my Application.mk is:
APP_STL := gnustl_shared
If I copy over the libgnustl_shared.so and treat it like another prebuilt shared lib, my problem is gone. Any idea why the APP_STL is not working properly. Note, I could have screwed something up. I just upgraded to using 7b. Using gnustl_shared used to work for me with other apps. Rolling back to 7 doesn't fix it. I think I have messed something up in Eclipse. I use Eclipse (windows) with sequoyah.
It looks like the linker is giving you an error. What you should do is the following:
Add a LOCAL_LDLIBS under your LOCAL_MODULE := test-libs. Here you need to include all the libraries you link against when you compile your pre-compiled libraries. So for example:
LOCAL_LDLIBS := -lgnustl_shared -lgcc -llog -landroid -lstdc++
Basically you need to identify what library contains the function __cxa_call_unexpected. A quick google shows that it's probably in libstdc++. Make sure that you also link with this library when creating your pre-compiled libraries.
I'm thinking it might have something to do with exceptions support.
Are you using exceptions in your code and if so are you compiling with a runtime library that supports exceptions? (and compiling with exceptions on)?.
There is more on this in the CPLUSPLUS-SUPPORT and STANDALONE-TOOLCHAIN files in the ndk docs.
I've observed a similar problem when one of my projects which contains only C source files (*.c) references another project that contains a c++ file(*.cpp). Application.mk files for both projects had APP_STL := gnustl_shared in them. The ndk version is ndk7e.
The solution was adding an empty C++ file (dummy.cpp) to the project that contained only .c files. Supposedly ndk understood that this project should be linked against the gnustl_shared and the build succeeded.

Categories

Resources