Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call C++ class methods or function from Java on android without recreating class/variable on every call

I have a pretty complex NLP code written on C++ and now I want to use it from my android app. My idea is to build app using client-server architecture, where client is an android java app, and server is a C++ Object Oriented code. But main problem for me, is that C++ components are pretty heavy (tokenizers, vectorizers, corpus data, etc) and I can't recreate them on every call, what I need is to create them once (on first request), and then have them in memory, handlind requests from java side when app is active.

Could you please give me some guidance how to achive this, since I never use C++ from Android before? Thanks in advance.


Java and C++ code isn't remote, there is no http or other remote requests involved, it's the same app. But to reduce ammount of overhead for inter Java/C++ communication I wan't to have a single point of contact in java code, something like NlpEngine.sendRequest(string textToProcess, int processingWorkflowId) and then C++ code based on processingWorkflowId identify, what it should do with text.

like image 373
silent_coder Avatar asked Mar 01 '17 09:03

silent_coder


People also ask

How do you call a method from another class without creating an object?

Static methods are the methods in Java that can be called without creating an object of class. They are referenced by the class name itself or reference to the Object of that class.

How do you call a class method from another class in Java?

We can call the private method of a class from another class in Java (which are defined using the private access modifier in Java). We can do this by changing the runtime behavior of the class by using some predefined methods of Java. For accessing private method of different class we will use Reflection API.

How do you call a method from another class in spring boot?

To do that, first, we need to create an object of “FirstClass” in the main method of the “SecondClass”. Once an object of the “FirstClass” is created, then we can invoke any method or attribute of the “FirstClass” within the “SecondClass” using that object.

How do you call a method in Android?

To call a method in Java, you type the method's name, followed by brackets. This code simply prints “Hello world!” to the screen. Therefore, any time we write helloMethod(); in our code, it will show that message to the screen.


1 Answers

Assumtion

I assume you have the C++ Code compiled for Android by using a tool set like Android NDK and the front end Java app is running on the same device as the back end C++ code.

Java Native Calls and Session State

No matter which of the three following interfaces you use. The C/C++ Libraries are loaded and stay in memory the whole time then Java application is running. The state of the library will be preserved the whole time. I don't clearly get the concern you have about initialization. It's not like starting a command on a CLI, where the other application is started and stopped over and over.

... But main problem for me, is that C++ components are pretty heavy (tokenizers, vectorizers, corpus data, etc) and I can't recreate them on every call ...

Loading Native Libraries in Java

There are some ways to load native libraries in Java, I want to point out three:

  • JNI - Java Native Interface

    JNI is a tool as old as Java itself. System calls from SWT were created using JNI. JNI is not the easy way, you have to define the functions/methods you want to make in Java as native, compile them to a C/C++ header, write the code for calling your library in this intermediate library. Compile this code for every ABI Platform (There are 7 Androids ABIs according to NDK). In the Java program you have find out the platform to call the ABI suitable intermediate library. JNI has many other pitfalls.

  • JNA - Java Native Access

    [JNA] is a java library that dynamically loads the C/C++ library by reflection. The definition of the Java call is done in pure java with no extra tool. The ease of usage has a trade-off in performance, the overhead of calling a function is up to 10 times slower than JNI. But that only plays a roll if you are calling extreme short running C/C++ library functions/methods very often. In your case it sound like you just call a few time the functions and these functions will take there time to run. JNA is used by Android developers.

  • JNR-FFI - Java Native Runtime

    JNR-FFI is the newest candidate. JNR-FFI is the part you use to call libraries.The other parts are the baseline for JNR-FFI. It's very much 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 a little slower than JNI (for getpid approx. 15%) but under some circumstances it can be faster than JNI. In the case of a long runtime on the C/C++ side this overhead does not matter. JNR is proposed to be in Java 9 as Standard Library JEP 191: Foreign Function Interface. The caveats: JNR-FFI seams to have some problems with Android.

Personal Experience

I had to implement some native library calls from Java. I started with JNI and after a week of testing an studying there were only few demo lines that worked. Every try took a long time, different tools, long building time. Than I found a presentation about the pitfalls of JNI and what side effects had to be considered. ...

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

I did not develop with JNA or JNR-FFI under Android. But in your case I would give JNA a try, because it is better supported with Android. I hopefully JNR-FFI gets implemented in Java 9 it is ease to switch from JNA code to a JNR-FFI code.

Example

I added and example of JNR-FFI to give you an idea of the ease of use. There is nothing more to do than to implement this few lines to be able to call a native c-library function.

JNR-FFI Example taken from Java Native Runtime - The 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();
    }
}
like image 191
notes-jj Avatar answered Oct 20 '22 06:10

notes-jj