2

I have a library say libraryOne.so (File1.c) which contains pure C code. Now I want to access this code from my Java file. For this I shall use the standard JNI procedure. But for using JNI, I should also modify the C code inside my File1.c (like including the header files for JNI and some standard JNIEXPORT stuff). So I am creating a wrapper library (libraryWrapper.so made from say File2.c). This library will contain the required JNI declarations and shall interact with my Java file. Now I want to know how can I call the pure C functions of File1.c from File2.c

Rock
  • 47
  • 7

1 Answers1

0

Firstly, you should read ndk-tutorial. Cause you need to setup ndk and so on. And after you can look for ndk samples to learn how to do things.And how to build

Actually Above is your answer. Coming to your question.

You should have source code of libraryOne.so. AS you say you have. Cause android target many platforms on which your so can not be run .so it need to be compiled with ndk

OK lets be our file File1.c

int myfunction(const char* st){
int answer=0;
  //stufs here
return answer;
}

Firstly, Add Java class from which we want to access

package example.com.myapplication;

public class JniClass {
    static {
        System.loadLibrary("libraryWrapper");
    }

    public   native int myFunction(String a );
}

Now we need wrapper. For this we should know jni interface. Fortunately there is tool called javah which can generate it for us and save us from doing it manually for all our calls. We should build our android project so that class files be generated. I build it with debug so my generated files will be on this /app/build/intermediates/classes/debug folder.

Ok then we run javah javah -jni example.com.myapplication.JniClass

if you got erros see Javah error while using it in JNI

It generated header file called example_com_myapplication_JniClass.h which contains

#include <jni.h>
/* Header for class example_com_myapplication_JniClass */

#ifndef _Included_example_com_myapplication_JniClass
#define _Included_example_com_myapplication_JniClass
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     example_com_myapplication_JniClass
 * Method:    myFunction
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_example_com_myapplication_JniClass_myFunction
  (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

OK now your answer. Easy way will be to to copy generated code and paste it on the bottom of File1.c code. and implementing it: Note that I named arguments env,obj and str after pasting it and cleaned comments

//..here your File1.c source code content
//
#include <jni.h> 
#ifdef __cplusplus
extern "C" {
#endif 
JNIEXPORT jint JNICALL Java_example_com_myapplication_JniClass_myFunction
  (JNIEnv * env, jobject obj, jstring str){

       const char * x=(*env)->GetStringUTFChars(env,str,0);
      //call our function
       int ret=  myfunction(x);
       (*env)->ReleaseStringUTFChars(env,str, x);

       return ret;

     }
#ifdef __cplusplus
}
#endif

But actually you might use header files on your c code. for example you could add generated header file and implement it on .c file. And on .c file you could include your File1.c header. And this way it be more clean way.

Assuming you already read ndk tutorial.And you setup ndk tools and know how to build

And finally we add File1.c to jni folder and change Android.mk file

LOCAL_MODULE := libraryWrapper LOCAL_SRC_FILES := File1.c and

APP_MODULES := libraryWrapper

then we build it with ndk-build which will add our so files to libs

Op wanted only with File1.c and File2.c inside File2.c

//declaration of funtions inside File1.c
extern int myfunction(const char* st);
#include <jni.h> 
    #ifdef __cplusplus
    extern "C" {
    #endif 
    JNIEXPORT jint JNICALL Java_example_com_myapplication_JniClass_myFunction
      (JNIEnv * env, jobject obj, jstring str){

           const char * x=(*env)->GetStringUTFChars(env,str,0);
          //call our function
           int ret=  myfunction(x);
           (*env)->ReleaseStringUTFChars(env,str, x);

           return ret;

         }
    #ifdef __cplusplus
    }
    #endif

And change Android.mk

LOCAL_SRC_FILES := File1.c 
LOCAL_SRC_FILES += File2.c 
Community
  • 1
  • 1
qwr
  • 3,660
  • 17
  • 29
  • The last part you said " Easy way will be to to copy generated code and paste it on the bottom of File1.c code. and implementing it:". I think this should be written to File2.c?? My actual requirement was not to do any changes in File1.c – Rock Sep 19 '15 at 10:46
  • 1
    yes cause other way you have to add forward declarations. But better use header files – qwr Sep 19 '15 at 10:48
  • Instead of File1.c add #include "File1.h" which will be your File1.c header file – qwr Sep 19 '15 at 10:49
  • I mentioned it on the answer too – qwr Sep 19 '15 at 10:51
  • 1
    I think we add the generated header file to File2.c. Why have you said to add it to File1.c? I don't want to make any changes to File1.c. – Rock Sep 19 '15 at 10:57
  • . As you mention you can add #include "gen_header file" . and write implementation inside File2.c. you can do the ways which suits you. THis way change adnroid.mk LOCAL_SRC_FILES := File2.c LOCAL_SRC_FILES +=File1.c and so on with LOCAL_SRC_FILES +="your_other cfiles" – qwr Sep 19 '15 at 11:01
  • Let me explain myself. I want to add the generated JNI header file to File2.c and want to know the way to call the File1.c function from File2.c. I don't want to make any changes in File1.c. How to achieve? – Rock Sep 19 '15 at 11:08
  • 1
    add declaration of your functions which inside File1.c that you want to call. compile will look for them and find definitions – qwr Sep 19 '15 at 11:13
  • added example based on my comments and File1.c inside answer. – qwr Sep 19 '15 at 11:45