JNI在C和C ++中调用不同的东西?

时间:2009-06-01 15:42:42

标签: java c++ c java-native-interface

所以我在C中使用了以下代码,它使用Java Native Interface但是我想将它转换为C ++,但我不确定如何。

 #include <jni.h>
 #include <stdio.h>
 #include "InstanceMethodCall.h"

 JNIEXPORT void JNICALL 
 Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
 {
     jclass cls = (*env)->GetObjectClass(env, obj);
     jmethodID mid = (*env)->GetMethodID(env, cls, "callback", "()V");
     if (mid == NULL) {
         return; /* method not found */
     }
     printf("In C\n");
     (*env)->CallVoidMethod(env, obj, mid);
 }

Java程序:

 class InstanceMethodCall {
     private native void nativeMethod();
     private void callback() {
         System.out.println("In Java");
     }
     public static void main(String args[]) {
         InstanceMethodCall c = new InstanceMethodCall();
         c.nativeMethod();
     }
     static {
         System.loadLibrary("InstanceMethodCall");
     }
 }

JNI与C和C ++交互的区别是什么?非常感谢任何帮助。

谢谢,皮特

5 个答案:

答案 0 :(得分:25)

我曾经有过这本书Essential JNI。虽然它有点过时,但其中大部分仍然有效。

如果我没记错的话,在C语言中,Java结构只是指针。因此,在您的代码中,“(*env)->”取消引用指针,以便您访问基础方法。

对于C ++,“env”实际上是一个对象 - 与C指针不同的实体。 (而且JNI实际上可以为你的C ++代码提供真正的对象来操作,因为C ++实际上支持对象。)所以“env->”在C ++中有不同的含义,它意味着“调用指向对象中包含的方法”通过“env”。

我认为另一个不同之处在于许多C-JNI函数要求您的一个参数为“JNIEnv *env”。所以在C中你可能不得不说(*env)->foo(env, bar)。使用c ++时,不需要第二次引用“env”,因此您可以改为“env->foo(bar)

不幸的是,我没有在我面前的这本书,所以我不能完全证实这一点!但我认为调查这两件事(特别是在谷歌或其他JNI代码中寻找它们)会让你走得很远。

答案 1 :(得分:6)

C和CPP中JNI呼叫的主要区别在于:

C风格的JNI看起来像 (* env) - &gt; SomeJNICall(env,param1 ...)

C ++风格的JNI看起来像 env-&gt; SomeJNICall(param1 ...)

所以要将它转换为你需要做的CPP

Java_InstanceMethodCall_nativeMethod(JNIEnv *env, jobject obj)
{
    jclass cls = env->GetObjectClass(obj);
    jmethodID mid = env->GetMethodID(cls, "callback", "()V");
    if (mid == NULL) {
        return; /* method not found */
}
printf("In C++\n");
env->CallVoidMethod(obj, mid);
//rest of your code

另外,请确保您的JNI功能遵循命名约定。

示例:

JNIEXPORT jint JNICALL Java_com_shark_JNITestLib_JNITestLib_startServer(JNIEnv* env, jobject o, jstring inputName, jstring streamName, jstring description) {

你可以看到约定 Java_(包名)_(classname)_(方法名)

因为上面的那个用于像

这样的课程
package com.shark.JNITestLib

import java.util.stuff;

public class JNITestLib 
{
    static
    {
        System.loadLibrary("myJNIlib");
    }

    public native synchronized int startServer(String inputName, String streamName, String description);

//more class stuff...
}

使用JNI时,我将其命名为包含JNI调用的类与该包的名称相同。这就是为什么你看到JNITestLib两次(这就是为什么我的JNI正常工作,因为我总是忘记如何正确命名JNI调用)

干杯,希望我帮忙:)。

答案 2 :(得分:5)

您是否尝试在extern "C"中包装C代码。有关更多信息,请参阅C++ Faq Lite,以及使用C ++编写C代码的其他可能机制。

答案 3 :(得分:2)

自从我触及标准C ++以来已经有一段时间了,但无论如何我都会尝试。

(*env)->”对我来说很奇怪。不应该只是“env->”吗?

也许我错了,它应该有效,但为什么事情会变得更复杂呢?

答案 4 :(得分:-1)

第一个代码是正确的C ++,不是吗?所以,你已经完成了!

说真的,你想在那段代码中改变什么?为什么呢?