Call C ++ class methods or functions from Java to android without recreating the class / variable with every call

I have a rather complicated NLP code written in C ++ and now I want to use it in my Android application. My idea is to create an application using the client-server architecture, where the client is an android java application and the server is object-oriented C ++ code. But the main problem for me is that C ++ components are quite heavy (tokenizers, vectorizers, case data, etc.), and I can’t recreate them with every call, I need to create them once (at the first request) and then have them in memory, process requests from the java side, when the application is active.

Could you give me some tips on how to achieve this since I have never used C ++ with Android before? Thanks in advance.


Java and C ++ - the code is not remote, there is no http or other remote requests, it is one and the same application. But in order to reduce the amount of overhead for exchanging between Java / C ++, I don’t want to have one point of contact in java code, something like NlpEngine.sendRequest(string textToProcess, int processingWorkflowId) , and then C ++ code based processingWorkflowId identifies what it should do with the text.

+7
java c ++ android android-ndk jni
source share
1 answer

Assumtion

I assume that you have C ++ code compiled for Android using a toolkit such as Android NDK, and the Java app on the front panel works on the same device as the C ++ code on the back panel.

Java native calls and session state

No matter which of the following three interfaces you are using. C / C ++ libraries load and remain in memory all the time, after which the Java application is executed. The library status will be saved all the time. I do not understand how you feel about initialization. This is not like running a command in the CLI, where another application starts and stops again and again.

... But the main problem for me is that C ++ components are quite heavy (tokenizers, vectorizers, case data, etc.), and I cannot recreate them with every call ...

Loading custom libraries in Java

There are several ways to load your own libraries in Java, I want to point out three:

  • JNI - Native Java Interface

    JNI is a tool as old as Java itself. System calls from SWT were created using JNI. JNI is not an easy way, you have to define the functions / methods that you want to do in Java as native, compile them into a C / C ++ header, write code to call your library in this intermediate library. Compile this code for each ABI platform ( There are 7 ABI androids according to NDK ). In the Java program, you will find a platform for invoking the appropriate ABI middleware library. JNI has many other pitfalls.

  • JNA - Native Java Access

    [JNA] is a Java library that dynamically loads the C / C ++ library by reflection. The definition of a Java call is performed in pure java without an additional tool. Ease of use has a trade-off in performance; the overhead of calling a function is up to 10 times slower than JNI. But this only plays a roll if you very often call extremely short C / C ++ library functions / methods. In your case, it sounds as if you just call functions several times, and these functions will be executed where necessary. JNA is used by Android developers.

  • JNR-FFI - Java Rative Runtime

    JNR-FFI is the newest candidate. JNR-FFI is the part that you use to invoke libraries. Other parts are basic to JNR-FFI. This is very inspired by JNA. Java code developed with JNA and with JNR-FFI looks very similar. The reason JNR-FFI was developed is performance. In general, JNR-FFI is slightly slower than JNI (to get about 15%), but in some circumstances it can be faster than JNI. In case of long work on the C / C ++ side, these overheads do not matter. The JNR is proposed to be in Java 9 as the standard library of JEP 191: External Function Interface . Cautions: JNR-FFI seams have some problems with Android.

Personal experience

I had to implement some native calls to the Java library. I started with JNI, and after a week of testing the training, there were only a few demo lines that worked. Each attempt took a lot of time, different tools, a long construction time. Then I found a presentation about the pitfalls of JNI and what side effects I had to consider ....

I found JNA. For several hours, the first demo code with my library worked, and compared to JNI it is so lightweight and quickly developing. I switched to JNR-FFI because it was a modern version of JNA. For what I did, performance was not the reason for the switch, it was only a positive side effect.

I did not develop JNA or JNR-FFI for Android. But in your case, I would try JNA, because it is better supported by Android. I hope JNR-FFI is implemented in Java 9, it is easy to switch from JNA code to JNR-FFI code.

Example

I added a JNR-FFI example to give you an idea of ​​ease of use. There is nothing more to do than to implement these few lines in order to be able to call your own c-library function.

JNR-FFI Example taken from Java Rative Runtime - Missing Link by Charles Oliver Nutter

 public class GetPidJNRExample { public interface GetPid { @IgnoreError long getpid(); } public static void main( String[] args ) { LibraryLoader<GetPid> loader = FFIProvider .getSystemProvider() .createLibraryLoader(GetPid.class); GetPid getpid = loader.load("c"); getpid.getpid(); } } 
+4
source share

All Articles