简体   繁体   中英

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 {
    *;
}

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM