I am sorry maybe this is stupid what I am asking, but I have a question about linking static/shared libraries in android.
I am creating a new C++ Native android studio project. After build, I open the apk file, and inside lib the folder there are placed libraries libnative-lib.so for every ABI. Size of APK is 3.580 KB.
But if I change inside CMakeLists.txt to build the native lib like Static lib, so now I got this:
add_library(native-lib
STATIC
native-lib.cpp)
When APK is built, I can not find the static library (libnative-lib.a). There is no lib folder in the apk. Also, the size is 2.836 KB.
Can someone please explain(or give me link for more info about this) where is the library placed in the STATIC build?
And on run I got error if I link static:
No implementation found for java.lang.String com.example.myapplication.MainActivity.stringFromJNI()
You can't use native static libraries directly in Android apps.
Android user space is basically a Java (or more precisely Dalvik VM).
So all user-facing applications must be written in Java or Kotlin (which both compile to Dalvik bytecode).
Static C/C++ libraries must be link in to a C/C++ executable or dynamic library to be used. They can not be loaded directly by Linux or Android.
Since Android app does not have a C/C++ executable in it, the only way to use a static library with an Android app is to link it with a dynamic library (*.so) that can be loaded via Java Native Interface.
Since JNI uses the system loader to load the library, it can only load dynamic libraries, and of those, only ones that export functions with proper naming conventions so they can be matched to a Java class that will be used to call the native code.
Related
I'm trying to use OpenCv 4 on Xamarin.Android by Java Binding Template. These are the steps that i've done:
0) I've compiled opencv binaries through cmake and mingw64 to get .jar and .a
I've put the .jar and the static libraries (.a) in Jars forlder of Xamarin Java Binding Template and i've compiled the template.
1.a) .jar Build Action is EmbeddedJar
1.b) libs Build Action is EmbeddedNativeLibrary
I've added a reference to that template in my Xamarin.Android project: the opencv methods were recognized correctly!
But, when i try to execute:
Mat Source = Imgcodecs.Imread(ImagePath, Imgcodecs.ImreadGrayscale);
i get an error:
Java.Lang.UnsatisfiedLinkError: 'No implementation found for long org.opencv.imgcodecs.Imgcodecs.imread_0(java.lang.String, int) (tried Java_org_opencv_imgcodecs_Imgcodecs_imread_10 and Java_org_opencv_imgcodecs_Imgcodecs_imread_10__Ljava_lang_String_2I)'
I think that there could be a missmatch of method name, maybe due to a wrong java parsing.
I've also tried to use shared libries (.so) by loading them through JavaSystem.LoadLibrary("LibraryNameWithoutInitialLib"), but i have the same error :/
Do you know why?
You cannot link static libraries with Xamarin.Android as the Xamarin/Mono NDK-based runtime is a static main entry executable and does not dynamically get built per project. If you do not need to use a .jar/.aar high-level wrapper, then you will need to use runtime shared libraries and define DllImportAttribute entries for the exported functions that you need to call.
Xamarin.Android supports the use of native libraries via the standard PInvoke mechanism.
Using Native Libraries
Use C/C++ libraries with Xamarin
Note: There are numerous OpenCV C# wrappers / DllImport files in open source ( i.e. a github search away 😁)
Note: If you are using a 3rd-party .jar/.aar , make sure that they are using OpenCV shared libraries and thus not requiring a gradle script to link them into an NDK-based Android app.
I'm trying to integrate this specific library to my Android project, and the library is written in C/C++. I've miraculously gotten ndk-build to give me the needed .so file.
However, looking at it, there's a sample in the project, and they use a mysterious .jar with the API bindings of the .c/c++ files.
How do i either
create this special .jar file that has the API, based on the .so?
OR
directly add a method to the main c++ file and then call it from Java?
I've tried to re-wrap things using JNI, but it definitely doesn't seem to work. i keep getting UnsatisfiedLinkError.
A lot of the documentation online uses jni as the tutorial. i'm happy with just a few links to tutorials on JNA.
JNA provides a stub native library, libjnidispatch.so for a variety of platforms. You can build this library yourself, or extract one of the pre-built binaries from the project's lib/native/<platform>.jar packages.
You include libjnidispatch.so in your Android project the way you would any other JNI library. This is required; you cannot rely on JNA to dynamically unpack and use its native library automatically like on other platforms. The JNA project includes details for doing so (as well as instructions for building libjnidispatch.so yourself).
You then use jna.jar as you would any other Java jar file, and write your own (Java) mappings to match the native library you're trying to access. There's also a jna-min.jar which omits all the native platform libraries that are normally bundled in jna.jar.
Do go to project properties and build paths and remove JNA 4.0 and related classes.
This will work!
I have a requirement to use C++ code developed using QT inside Xamarin.
The process is like (all done on Windows):
1. Configure and create a static library in QT 5.2
2. Add an Android build kit (MinGW 32) and build the static library for armeabi
3. Use the static library to do P/Invoke inside C# in Xamarin
The problem is that Step 2 above produces a .a file. This is a Linux native object file and I am very sure it will run in Android. How do I use it to perform DllImport and do a P/Invoke? Pardon my ignorence here, I have tried to rename the file to .so and it didn't really help.
Let me know if you need any clarification, your suggestion is very much appreciated.
Thanks, Manoj
You are building a static library. These are meant to be included and loaded at compile time for the programs that use them. What you want it to build a library that can be loaded dynamically, which should end in .so (no you can't just rename it).
You likely need a dynamic library in QT too.
So , I have installed Ubuntu(but still use the Android kernel) on my Android phone with the intention of using it to compile native code for the device using the glibc.
I made a library, which I plan to use it in an app which I want to make, using JNI, but I am using the math library. My question is:
Is there a way to include these libraries into the library that I
created so that my phone can use the glibc library instead of the
bionic(which is what the NDK uses) library?
NOTE: I have tried making a test program that uses the library and statically links to make sure that the compiled code would work on the android OS and not just Ubuntu, and I came to the conclusion that it does :) So any answer pertaining to my question would be a great help.
You can use ar to extract the original .o files from any .a files:
ar x libm.a
You can then select whichever .o files you like and link them into your own code.
.a library files can be viewed as tar files with extra symbol-index features (although I don't know how similar the internals are).
WARNING: in general, you can only use .o files from static libraries in your main application. If you try to link them into a shared library (.so file) you may be out of luck. The .o file needs to have been created with -fPIC for that to work, and this is often not the case for static libraries.
I'm new to Android's NDK and I don't understand the differences between static and shared libraries. What are they, and when would I choose one type over the other?
The term shared library is not a perfect fit regarding Android's NDK, because in many cases the .so libraries aren't actually shared between applications. It's better to classify the libraries that the NDK builds as static and dynamic.
Every Android application is a Java application, and the only entry point for the NDK code is loading it as a dynamic library and call it trough JNI.
Static libraries are an archives of compiled object files. They get bundled in other libraries at build time. Unused portions of code from static libraries are stripped by the NDK to reduce total size.
Dynamic libraries are loaded at runtime from separate files. They can contain static libraries that they are dependent on or load more dynamic libraries.
So what you actually need for Android development is at least one shared library, that will be called from Java code, and linked with it's dependencies as static libraries preferably.
Native shared libraries: The NDK builds these libraries, or .so files, from your native source code.
Native static libraries: The NDK can also build static libraries, or .a files, which you can link against other libraries.
This is according to NDK Documentation
Static libs – all library binaries will be included as part of our executable during the linking process. Thus, we won’t need the libs anymore, but it’ll increase the size of our executable file.
Shared libs – the final executable only has references to the libs, not the code itself. It requires that the environment in which we run our executable has access to all the files of the libs used by our program.