从 JNI 调用静态 void Java 方法

Kno*_*sos 3 java java-native-interface android

我的 C 代码无法找到我在 Java 中的公共静态函数调用。它设法找到了没有错误的类。

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

我在 StackOverflow 上似乎有类似的问题,但到目前为止似乎没有任何变化有帮助。也许我有逻辑错误?

我的 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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

    ...

    cec_debug_msg(env, &rx_msg);

    ...

}
Run Code Online (Sandbox Code Playgroud)

我的 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!");
    }

}
Run Code Online (Sandbox Code Playgroud)

签名检查:

javap -s -p CECUtils

public static void onResponse(int);

签名:(I)V

解决方案:检查 ProGuard!

-keep public class com.example.utils.CECUtils {
    *;
}
Run Code Online (Sandbox Code Playgroud)

小智 6

尝试使用GetStaticMethodID代替GetMethodID.

请注意,您将需要调用CallStaticVoidMethod而不是CallVoidMethod也。

有关更多信息,请参见此处:http : //journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html


ral*_*htp 5

请参阅方法签名http://journals.ecs.soton.ac.uk/java/tutorial/native1.1/implementing/method.html

\n\n

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

\n\n

这是 GetMethodID 的文档:

\n\n
\n

获取方法ID

\n\n

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

\n\n

返回类或接口的实例(非静态)方法的方法 ID。\n 该方法可以在 clazz\xe2\x80\x99s\n 超类之一中定义并由 clazz 继承。该方法由其名称和签名确定。\n

\n\n

GetMethodID() 会导致初始化未初始化的类。

\n\n

要获取构造函数的方法 ID,请提供方法名称并提供 void (V) 作为返回类型。

\n
\n\n

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

\n\n
\n

使用javap生成方法签名

\n\n

为了消除手动派生方法签名时出现的错误,您可以使用 javap 工具打印方法签名。例如,通过\n运行:

\n\n
javap -s -p Prompt\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以获得以下输出:

\n\n
Compiled from Prompt.java\nclass Prompt extends java.lang.Object \n    /* ACC_SUPER bit set */\n{\n    private native getLine (Ljava/lang/String;)Ljava/lang/String;\n    public static main ([Ljava/lang/String;)V\n    <init> ()V\n    static <clinit> ()V\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n

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

\n