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
-
If you got File1.c source code then compile both for android – qwr Sep 19 '15 at 09:03
-
Can you please tell me the detailed way for doing this? – Rock Sep 19 '15 at 09:06
-
Do you know how to build with ndk? – qwr Sep 19 '15 at 09:20
-
I am afraid but I don't :( – Rock Sep 19 '15 at 09:29
-
3You should look for android ndk tutorial first. – qwr Sep 19 '15 at 09:33
1 Answers
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.JniClas
s
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
-
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
-
1yes 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
-
-
1I 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
-
1add 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
-