如何使用JNI从C语言调用JAVA方法

4

我希望使用JNI(Java Native Interface)调用特定的Java setter方法,并将一个short[]缓冲区作为参数传递给它。

Java方法的实现如下:

public void setPcmLeft(short[] data) { pcm_l = data; }

在我的 C 函数内部,我该如何使用 JNI 调用这个方法。

目前我的代码如下:

void Java_com_companyName_lame_LameActivity_lameDecode(JNIEnv *env, jobject jobj)
{
    jclass class = (*env)->GetObjectClass(env, jobj);

    if (class != NULL) {

        jmethodID setLeftDatatID = (*env)->GetMethodID(env, class, "<setPcmLeft>", "void(V)");
        if (setLeftDatatID == NULL) {
            LOGD("(Lame) No method setLeftData");
        }  
    } 
}

当我运行这个程序时,setLeftDataID 始终为 NULL
请注意,jobj 参数是传递给我的对象,其中包含了 setPcmLeft 的实现。
2个回答

3
在调用 GetMethodID() 时,方法名不需要尖括号,签名需要匹配Java方法。
jmethodID setLeftDatatID = (*env)->GetMethodID(env, class, "setPcmLeft", "([S)V");

一般来说,签名的形式为(arg-types)ret-type,编码方式如下链接所示。参数是[S编码的short[]。返回类型为void时,返回类型为V
更多信息请参见Oracle JNI指南第3章

我们什么时候需要使用尖括号?我看到一些代码像这样 jmethodID m_mid = env -> GetMethodID(m_cls,"<init>","()V"); - smwikipedia
1
@smwikipedia - 你需要在特殊名称<init>中使用它们,这是GetMethodID()支持的,以允许引用构造函数。 "要获取构造函数的方法ID,请将<init>作为方法名称并将void(V)作为返回类型。" -- 来自http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/functions.html中`GetMethodID()`文档的说明。 - Andy Thomas

1

试试这个:

   jmethodID midCallBack = (*env)->GetMethodID(env, class, "setPcmLeft", "([S)V");

您可以使用 CallVoidMethod*() 函数之一。 - Andy Thomas
他可能使用了你之前的版本,但没有加上“[S”。 - Andy Thomas
抱歉我删除了那条评论,我在代码中犯了一个错误。我漏掉了 [S。感谢你的回答。 - Sabobin
啊,是的,我错过了参数,直到你发布了你的之后才注意到。 - Amir Afghani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接