从 JNI 调用 static void Java 方法

Calling a static void Java method from JNI

我的 C 代码无法找到我在 Java 中的 public 静态函数调用。它成功地找到了 class。

我正在尝试 return 回调方法 onResponse 的结果。 “5”稍后会被更复杂的东西取代。

我在 Whosebug 上似乎遇到过类似的问题,但到目前为止似乎没有任何改变。也许我有逻辑错误?

我的 JNI(更新 #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);
        }
    }
}

此代码包含在从此函数调用的方法中:

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

    ...

    cec_debug_msg(env, &rx_msg);

    ...

}

我的Java(更新#1):

public class CECUtils {

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

    public static native int startListening();

    ...

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

}

签名检查:

javap -s -p CECUtils

public static void onResponse(int);

Signature: (I)V

解决方法:检查 ProGuard!

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

尝试使用 GetStaticMethodID 而不是 GetMethodID

请注意,您还需要调用 CallStaticVoidMethod 而不是 CallVoidMethod

查看此处了解更多信息:http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html

查看方法签名 (http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html)

jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "(I)V"); (I)V 确定签名

这是 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.

也许您可以使用 javap 来确定您的方法的签名:

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
}

“-s”标志通知 javap 输出签名而不是正常的 Java 类型。 “-p”标志导致包含私有成员。