Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android ndk UnsatisfiedLinkError when using a prebuilt shared library

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

like image 857
Ita Avatar asked Mar 14 '11 14:03

Ita


2 Answers

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

like image 106
Ita Avatar answered Nov 09 '22 15:11

Ita


  1. 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, ...)
    
  2. 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...

like image 26
Roy Samuel Avatar answered Nov 09 '22 15:11

Roy Samuel