I am trying to build a JNI interface to an existing C++ code base. I have successfully built a .so file for my JNI function, and can successfully call that function from within Java code.
When I move to the next step, which is to call a function in libpng (compiled to a .so file with the NDK tool chain), I am able to successfully build the shared library associated with my JNI function, and the .MK file causes libpng12.so to be copied into the libs/armeabi directory as it should.
Deploying the application to the emulator places both the JNI .so and the libpng.so into the lib directory of the application folder under /data. Calling System.loadLibrary for my JNI library causes that code to be found in my application's lib directory.
However, I then get an UnsatisfiedLinkError when the code tries to access the libpng.so file. Using strace on the emulator, I see that it is trying to load the libpng.so from /system/lib, rather than from the same location that the JNI library was loaded from.
Is there some way to control where referenced libraries are loaded from? It doesn't seem that they should have to be installed in /system/lib; the fact that deploying the application places the referenced .so file in the app's lib dirctory seems to indicate that it would be found there.
For what it's worth, here's the .MK file we are using:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := png12
LOCAL_SRC_FILES := libpng12.so
LOCAL_EXPORT_C_INCLUDES := /home/jipping/libpng-1.2.44
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := PNGLib
LOCAL_SRC_FILES := PNGLib.cpp
LOCAL_SHARED_LIBRARY := png12
LOCAL_LDLIBS := -L/cygdrive /c/Users/mcfall/workspace/AndroidCalculator/jni -lpng12
LOCAL_C_INCLUDES := /home/mcfall/libpng-1.2.44
include $(BUILD_SHARED_LIBRARY)
Thanks in advance for any help.
Try loading the libpng12.so using System.loadLibrary as well. Do this before loading your jni library so all needed symbols are already loaded.
Related
I'm trying to use a C++ function (that is referenced using a .so file) from my C JNI code. To illustrate my project architecture, it looks like this:
Java -> C (JNI) -> C++ function
This is what my Android.mk file looks like:
LOCAL_PATH := $(call my-dir)
# My C++ library
include $(CLEAR_VARS)
LOCAL_MODULE := my_module
LOCAL_SRC_FILES := ../../../../../../module_service/lib/system/lib/libmodule_service.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
# JNI C code
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_C_INCLUDES += ../../../../../module_service/src
LOCAL_SHARED_LIBRARIES := my_module
include $(BUILD_SHARED_LIBRARY)
Using "ndk-build" command, my project builds. But when I try to run it on my device, it crashes with the following message:
java.lang.UnsatisfiedLinkError: ... nativeLibraryDirectories=[/data/app/com.sampleapp.mysampleapplication-1/lib/arm, /vendor/lib, /system/lib]]] couldn't find "liblibmodule_service.so"
What is adding another "lib" to my .so file? If I create another .so file named "liblibmodule_service.so" (in addition to "libmodule_service.so") in my /system/lib directory, it works. But that feels like a hacky solution, and I would prefer to not have both "libmodule_service.so" AND "liblibmodule_service.so" which are the same exact files.
Any help would be greatly appreciated. Thanks!
I guess you may be using System.loadLibrary("libmodule_service"); to load the library, change it to System.loadLibrary("module_service");
After a great deal of pain, I have finally built UHD for android. I use a script that takes a standard UHD package and builds everything with the android tools. I then take the resulting libraries and include files and put them under the jni directory. This is what my directory structure looks like
> jni
> uhd
- Android.mk
> lib
- libuhd.so
- libuhd.so.003
- libuhd.so.003.005
> pkgconfig
- uhd.pc
> include
- *.hpp
Here is my Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := uhd
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_SRC_FILES := lib/libuhd.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
Everything build nicely when I include it in my project. The problem comes in when I put it on the device. The app immediately crashes. Looking at the log file gives me the following message
E/dalvikvm(20135): dlopen("/data/app-lib/com.myproject-1/libmyproject.so") failed: dlopen failed: could not load library "libuhd.so.003" needed by "libmyproject.so"; caused by library "libuhd.so.003" not found
So (no pun intended) I changed the LOCAL_SRC_FILES to be the libuhd.so.003, but android throws an error telling me that I am not allowed to do that. A prebuilt shared library must end in .so, not .so.003. I have also tried copying the library to the /libs folder in the base directory of the project, but that doesn't seem to work either.
How can I either change the library name or change what myproject.so is looking for?
Thanks.
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
I have two Android projects, one is a shared library and one is my application's project. Both projects contain some Java and some native code. When I try and run my APK I receive the following error:
Error generating final archive: Found duplicate file for APK: lib/armeabi/libOEShared.so
My shared library is marked as a library project (Properties->Android->'Is Library') so that I am able to use it's Java code. This presumably copies libOEShared.so for me once.
In order to link my Applications native code with libOEShared I use the NDK Prebuilds feature. Here is my Android.mk:
#include shared library
include $(CLEAR_VARS)
LOCAL_MODULE := OEShared
LOCAL_SRC_FILES := ../../../Shared/OEShared/libs/armeabi/libOEShared.so
include $(PREBUILT_SHARED_LIBRARY)
#build App library
include $(CLEAR_VARS)
LOCAL_MODULE := OEApp
LOCAL_SRC_FILES := OEApp.cpp
LOCAL_LDLIBS := -llog -lGLESv2 -lz
LOCAL_SHARED_LIBRARIES := OEShared
include $(BUILD_SHARED_LIBRARY)
However, the NDK also copies libOEShared into my Application project's lib folder, resulting in two copies being present in the final APK.
How can I link my Application's native code to libOEShared without it being automatically duplicated?
Thank you for you time, this has caused me a lot of frustration so far.
Only linking is required here, instead of build. Linking can be done by using LOCAL_LD_LIBS flag. You can try this.
LOCAL_LDLIBS := -L$(LOCAL_PATH)/../../../Shared/OEShared/libs/$(TARGET_ARCH_ABI)/ \
-lOEShared
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.