Petey B
Petey B

Reputation: 11569

JNI Calls different in C vs C++?

So i have the following code in C that utilizes Java Native Interface however i would like to convert this to C++ but am not sure how.

 #include <jni.h>
 #include <stdio.h>
 #include "InstanceMethodCall.h"

 JNIEXPORT void JNICALL 
 Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
 {
     jclass cls = (*env)->GetObjectClass(env, obj);
     jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V");
     if (mid == NULL) {
         return; /* method not found */
     }
     printf("In C\n");
     (*env)->CallVoidMethod(env, obj, mid);
 }

Java Program:

 class InstanceMethodCall {
     private native void nativeMethod();
     private void callback() {
         System.out.println("In Java");
     }
     public static void main(String args[]) {
         InstanceMethodCall c = new InstanceMethodCall();
         c.nativeMethod();
     }
     static {
         System.loadLibrary("InstanceMethodCall");
     }
 }

What are the differences in which JNI interacts with C and C++? Any help is greatly appreciated.

Thanks, Pete

Upvotes: 32

Views: 17052

Answers (4)

poundifdef
poundifdef

Reputation: 19353

I used to have the book Essential JNI. And while it is kinda dated (1998), much of it still works today.

If I recall correctly, in C, Java constructs are simply pointers. Thus, in your code, (*env)-> is dereferencing pointers to give you access to the underlying methods.

For C++, env is actually an object – a different entity than a C pointer. (And JNI can actually provide real objects for your C++ code to manipulate, since C++ actually supports objects.) So env-> has a different meaning in C++, it means "call the method that is contained in the object pointed to by env.

The other difference, I believe, is that many of the C-JNI functions require that one of your parameters be the JNIEnv *env. So in C you might have to say (*env)->foo(env, bar). With C++, the second reference to env is not necessary, so you can instead say env->foo(bar).

Unfortunately, I don't have the above book in front of me, so I can't quite confirm this! But I think investigating those two things (specifically looking for them on Google or in other JNI code) will get you pretty far.

Upvotes: 28

Shark
Shark

Reputation: 6610

The main difference between JNI calls in C and CPP is this:

C-style JNI looks like (*env)->SomeJNICall(env, param1 ...)

C++ style JNI looks like env->SomeJNICall(param1 ...)

so to convert it to CPP you need to do

Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
{
    jclass cls = env->GetObjectClass(obj);
    jmethodID mid = env->GetMethodID(cls, "callback", "()V");
    if (mid == NULL) {
        return; /* method not found */
}
printf("In C++\n");
env->CallVoidMethod(obj, mid);
//rest of your code

Also, make sure that your JNI functions follow the naming convention.

Example:

JNIEXPORT jint JNICALL Java_com_shark_JNITestLib_JNITestLib_startServer(JNIEnv* env, jobject o, jstring inputName, jstring streamName, jstring description) {

You can see that the convention is Java_(package name) _ (classname) _ (methodname)

since the one above was used in a class like

package com.shark.JNITestLib

import java.util.stuff;

public class JNITestLib 
{
    static
    {
        System.loadLibrary("myJNIlib");
    }

    public native synchronized int startServer(String inputName, String streamName, String description);

//more class stuff...
}

When working with JNI i made it a convention to name the class containing JNI calls to be the same name as the package. Thats why you see JNITestLib twice (and thats why my JNI works right off the bat because I always forget how to properly name the JNI calls)

Cheers, hope I helped :)

Upvotes: 9

michael aubert
michael aubert

Reputation: 6826

It's been a while since I touched standard C++ but I'm gonna try it anyway.

"(*env)->" looks weird to me. Shouldn't that simply be "env->" ?

Maybe I'm wrong and it is supposed to work, but why make things more complicated anyways?

Upvotes: 2

Brian
Brian

Reputation: 25834

Have you tried wrapping your C code in an extern "C". See C++ Faq Lite for more information, and for other possible mechanisms to let you use your C code with C++.

Upvotes: 5

Related Questions