3

I asked this question the other day, but wasn't too specific, so I want to re-clarify.

I am creating an Android Application which uses an existing library in C using the NDK. The problem I have run into is that the C code uses a lot of things java doesn't ( function pointers as parameters is the big problem ).

Anyway, I was wondering if I could write functions in my Java code that the C code calls. Now from what I can tell, you can do it, so I would appreciate it if no one just answered 'Yes you can, LINK." I have been looking into it but its very over my head as to what actually needs to be done.

Can anyone try to explain the process? I know it involves creating a JVM in the C code; any information that will help a newbie get on his feet will be greatly appreciated.

Thanks

EDIT :

So, I don't know what to do for these three steps.

To call a specific Java function from C, you need to do the following:

Obtain the class reference using the FindClass(,,) method.
Obtain the method IDs of the functions of the class that you want to call using the 
GetStaticMethodID and GetMethodID function calls.

Call the functions using CallStaticVoidMethod, CallStaticIntMethod, and CallStaticObjectMethod.

This isn't explained too much and I have literally no experience in C. Is FindClass a C method?

JuiCe
  • 4,132
  • 16
  • 68
  • 119
  • 1
    I know you said you just didn't want a link, but this is about as easy as it can be explained: http://www.codeproject.com/Articles/22881/How-to-Call-Java-Functions-from-C-Using-JNI . It's definitely not a subject where a few lines of code will cover all you need to know. – AlcoJaguar Jul 24 '12 at 17:23
  • I started looking over what you sent but still am not sure of a few things. If you have time, take a look at what I've edited and let me know if you can help. – JuiCe Jul 24 '12 at 19:33
  • I don't think you can just go create a VM on Android. It has its own VM, and the Android platform controls how it gets invoked. Rather, I think you want [this method](http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html) to call the Java code back from C. – mpontillo Jul 24 '12 at 21:45

1 Answers1

4

Every C function that is callable from Java via JNI has a first parameter of type JNIEnv*. On the C end, this is a pointer to a pointer to a structure with a bunch of pointers to functions. Those functions are your interface to the Java world. FindClass, GetMethodID and the rest are among them.

So when you want to call FindClass from the C side, here's how you do it:

void Java_com_mypackage_MyClass_MyMethod(JNIEnv *jniEnv, jobject thiz)
{
    jclass *clazz = (*(*jniEnv)->FindClass)(jniEnv, "com/mypackage/SomeClass");
    jmethodID MethodID = (*(*jniEnv)->GetStaticMethodID)(jniEnv, clazz, "SomeMethod", "(I)I");
    int result = (*(*jniEnv)->CallStaticIntMethod)(jniEnv, clazz, MethodID, 18);

And so forth. The line dereferences the jniEnv parameter, gets a function pointer and calls the function through it. Class and method names are completely bogus, naturally. How would I know yours.

Note: I'm talking of function pointers here, but not in the same sense as you do; those are function pointers to functions that JNI provides, not to your functions.

The verbosity of call syntax has to do with the limitations of C; in C++, you can write instead

jclass *cl = jniEnv->FindClass("com/mypackage/SomeClass");

as C++ supports function table pointers of this sort natively via virtual functions.

You can probably take some shortcuts along the way. If you're calling methods in the same class as your C point of entry, and it happens to be static, your second parameter already is a class object pointer. If you have a this pointer to the object you want to invoke a method on, you can use GetObjectClass.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • You say every C function that is callable from Java...but isn't that just what the NDK is used for? Everything I've read about the NDK never said anything about using `JNIEnv*`. I only came across that when I wanted to go back and call Java functions from my C code, which had been already called from Java. It sounds wild I know, but its what I've been asked to do. – JuiCe Jul 25 '12 at 12:08
  • I NEVER said that every C function is callable from Java. That;s not the case. I said that every callable function has a JNIEnv* parameter. – Seva Alekseyev Jul 25 '12 at 12:41
  • OK I know that, `every C function that IS callable` I said. But I haven't read anywhere in the past that that's true. I was trying to understand your wording...did you mean every function in Java that is callable from C? What I am trying to do is, starting in Android, make a call to a C function, and then within that C function, make a call back to a different Android function. – JuiCe Jul 25 '12 at 13:01
  • You're saying that if a C function is callable from Java, it needs that as a first parameter. And I see that no where. The only time `JNIEnv*` comes into play is when there is a need for a Java function to be callable from C, correct? – JuiCe Jul 25 '12 at 13:32
  • Every function in Java is callable from C, yes. But not the other way around. Just in case, here's [another "intro to JNI" post that I wrote the other day](http://stackoverflow.com/questions/11354411/android-ndk-native-function-call-issue/11354714#11354714). It deals specifically with the callability-from-Java issue. Maybe it helps... – Seva Alekseyev Jul 25 '12 at 13:32
  • Oh, and about the JNIEnv. From [this document](http://docs.oracle.com/javase/1.4.2/docs/guide/jni/spec/design.html#wp16696): "The JNI interface pointer is the first argument to native methods. The JNI interface pointer is of type JNIEnv. The second argument differs depending on whether the native method is static or nonstatic. The second argument to a nonstatic native method is a reference to the object. The second argument to a static native method is a reference to its Java class. " – Seva Alekseyev Jul 25 '12 at 13:36
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/14404/discussion-between-juice-and-seva-alekseyev) – JuiCe Jul 25 '12 at 13:42
  • I don't have anything else to say. Thanks for your help. I have a lot more reading to do before I start coding. – JuiCe Jul 25 '12 at 14:06
  • Another question if possible, are jclass and jmethodID built in C types? I have no experience with C at all. – JuiCe Jul 25 '12 at 14:46
  • No, they're defined in jni.h, which you have to #include first thing in the C file. It's kinda like "using" in Java. If you're new to C, start with Android's JNI examples - "hello-jni" and such. – Seva Alekseyev Jul 25 '12 at 15:32
  • I have a simple question as am a newbie to ndk. instead of calling void Java_com_mypackage_MyClass_MyMethod can i call only MyMethod() in c file. is it possible. If no can you please tell me why it is not possible. – AndroidOptimist May 15 '14 at 06:59
  • @AndroidOptimist: please ask your question as a separate question. JuiCe's question has been answered long time ago. StackOverflow is not a forum. – Seva Alekseyev May 15 '14 at 11:32