K.E. K.E. - 4 months ago 39
C++ Question

Call prebuilt C++ shared library from Android with JNI

I want to use a prebuilt C++ library from Android via JNI. Therefore I am working with Android Studio.

I am building the project with com.android.tools.build:gradle-experimental:0.7.0-alpha4 and my build.gradle looks like this:

apply plugin: "com.android.model.application"

model {
repositories {
libs(PrebuiltLibraries) {
rexxlib {
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("src/main/jniLibs/armeabi/librexx.so")
}
}
rexxapilib {
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("src/main/jniLibs/armeabi/librexxapi.so")
}
}
}
}



android {
compileSdkVersion 23
buildToolsVersion "23.0.3"

defaultConfig {
applicationId "org.oorexx.oorexxforandroid"
minSdkVersion.apiLevel 19
targetSdkVersion.apiLevel 23
versionCode 1
versionName "1.0"
buildConfigFields {
create() {
type "int"
name "VALUE"
value "1"
}
}
}

ndk {
moduleName "rexxwrapper"
}

buildTypes {
release {
minifyEnabled false
proguardFiles.add(file("proguard-rules.pro"))
}
}

// Configures source set directory.
sources {
main {
java {
source {
srcDir "src/main/java"
}
}
jniLibs {
dependencies {
library "rexxlib"
library "rexxapilib"
}

}
}
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:design:23.3.0'
}


I created a wrapper C library to call the prebuilt library from there.

#include "org_oorexx_oorexxforandroid_jniwrapper_RexxWrapper.h"
#include <jni.h>

JNIEXPORT jstring JNICALL Java_org_oorexx_oorexxforandroid_jniwrapper_RexxWrapper_callrexx(JNIEnv *env, jobject instance) {

//TODO: call function of prebuilt library librexx.so - What todo?

return (*env)->NewStringUTF(env, "Hello From Jni");
}


My Java class for the wrapper:

public class RexxWrapper {

private native String callrexx();

static public void execute(String argv[]) {
RexxWrapper rexxWrapper = new RexxWrapper();
System.out.println("--> "+rexxWrapper.callrexx());
}

static {
System.loadLibrary("rexx");
System.loadLibrary("rexxwrapper");
}

}


I have created a test-method in my shared library (C++) which looks like this:

int AndroidRexxStart()
{
return 1;
}


Everything is working fine, and I get the response from my wrapper c library. Now I want to call a function
AndroidRexxStart()
of the prebuilt library
librexx.so
in my wrapper library and I do not know how to do that. What I have to include and how can I call the method?

EDIT:
My Projectstructure:
enter image description here

Answer

You've made a Java wrapper for the library but you also need to make a JNI wrapper for the Java to call. So you'll need JNI methods for each of the library methods you want to call. I don't know what LibRexx is so I don't know what you would want to call but you just need to expose those in JNI so they can be called from Java.

First, you're rexxWrapper should be linking in librexx so you shouldn't need to load it in Java. Second you can just create another JNI method like this:

JNIEXPORT jint JNICALL Java_org_oorexx_oorexxforandroid_jniwrapper_RexxWrapper_start(JNIEnv *env, jobject instance) {

    return AndroidRexxStart();
}

Then in your AndroidRexxStart() you would actually call into the librexx to start it.

In Java you'll add:

private native String start();

to call the JNI method. The naming of the JNI method is important. It has to match the Java path, class and method name that you want to use.

Comments