Knossos
Knossos

Reputation: 16038

Calling a static void Java method from JNI

My C code does not manage to find the public static function call I have in Java. It manages to find the class without error.

I am attempting to return a result to a callback method onResponse. "5" will be replaced by something more complex later.

I have seem similar questions on StackOverflow, but no changes so far seem to have helped. Perhaps I have a logic error?

My JNI (updated #2):

void cec_debug_msg(JNIEnv *env, cec_rx_message_t* msg) {
    jclass cls = (*env)->FindClass(env, "com/example/utils/CECUtils");
    if(!cls) {
        LOGE("Could not find the CEC class.");
    } else {
        jmethodID methodid = (*env)->GetStaticMethodID(env, cls, "onResponse", "(I)V");
        if(!methodid) {
            // Code always reaches this point, never finding the method
            LOGE("Could not find the callback method.");
        } else {
            LOGV("Called static void method.");
            (*env)->CallStaticVoidMethod(env, cls, methodid, 5);
        }
    }
}

This code is contained in a method that is called from this function:

JNIEXPORT int JNICALL Java_com_example_utils_CECUtils_startListening(JNIEnv *env, jclass cls) {

    ...

    cec_debug_msg(env, &rx_msg);

    ...

}

My Java (updated #1):

public class CECUtils {

    static {
        System.loadLibrary("cecutils");
    }

    public static native int startListening();

    ...

    public static void onResponse(int opcode) {
        Utils.log("CEC", "From JNI!");
    }

}

Signature check:

javap -s -p CECUtils

public static void onResponse(int);

Signature: (I)V

Solution: Check ProGuard!

-keep public class com.example.utils.CECUtils {
    *;
}

Upvotes: 4

Views: 16178

Answers (2)

ralf htp
ralf htp

Reputation: 9422

see the method signatures (http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html)

jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); the (I)V determines the signature

Here is the docs of GetMethodID:

GetMethodID

jmethodID GetMethodID(JNIEnv *env, jclass clazz, const char *name, const char *sig);

Returns the method ID for an instance (nonstatic) method of a class or interface. The method may be defined in one of the clazz’s superclasses and inherited by clazz. The method is determined by its name and signature.

GetMethodID() causes an uninitialized class to be initialized.

To obtain the method ID of a constructor, supply as the method name and void (V) as the return type.

maybe you can use javap to determine the signature of your method:

Using javap to Generate Method Signatures

To eliminate the mistakes in deriving method signatures by hand, you can use the javap tool to print out method signatures. For example, by running:

javap -s -p Prompt

you can obtain the following output:

Compiled from Prompt.java
class Prompt extends java.lang.Object 
    /* ACC_SUPER bit set */
{
    private native getLine (Ljava/lang/String;)Ljava/lang/String;
    public static main ([Ljava/lang/String;)V
    <init> ()V
    static <clinit> ()V
}

The "-s" flag informs javap to output signatures rather than normal Java types. The "-p" flag causes private members to be included.

Upvotes: 5

Damien O&#39;Reilly
Damien O&#39;Reilly

Reputation: 992

Try using GetStaticMethodID instead of GetMethodID.

Note, you will need to call CallStaticVoidMethod instead of CallVoidMethod also.

See here for more info: http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html

Upvotes: 7

Related Questions