从 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”标志导致包含私有成员。
我的 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”标志导致包含私有成员。