从JNI调用静态void Java方法

时间:2015-10-12 09:02:40

标签: java android java-native-interface

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

我试图将结果返回给回调方法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); } } } 。 " 5"将被更复杂的事物取代。

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

我的JNI(已更新#2):

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

    ...

    cec_debug_msg(env, &rx_msg);

    ...

}

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

public class CECUtils {

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

    public static native int startListening();

    ...

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

}

我的Java(更新#1):

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

签名检查:

  

javap -s -p CECUtils

     

public static void onResponse(int);

     

签名:(I)V

解决方案:检查ProGuard!

{{1}}

2 个答案:

答案 0 :(得分:4)

尝试使用GetStaticMethodID代替GetMethodID

注意,您还需要拨打CallStaticVoidMethod而不是CallVoidMethod

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

答案 1 :(得分:2)

查看方法签名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 );

     

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

     

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

     

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

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

  

使用javap生成方法签名

     

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

javap -s -p Prompt
     

您可以获得以下输出:

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
}

&#34; -s&#34; flag通知javap输出签名而不是普通的Java类型。 &#34; -p&#34; flag会导致私有成员被包含在内。