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

Pet*_*y B 31 c c++ java 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);
 }
Run Code Online (Sandbox Code Playgroud)

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

JNI与C和C++交互的区别是什么?任何帮助是极大的赞赏.

谢谢,皮特

pou*_*def 26

我曾经有过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代码中寻找它们)会让你相当远.


Sha*_*ark 6

C和CPP中JNI调用的主要区别在于:

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

C++风格的JNI看起来像env-> 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
Run Code Online (Sandbox Code Playgroud)

此外,请确保您的JNI函数遵循命名约定.

例:

JNIEXPORT jint JNICALL Java_com_shark_JNITestLib_JNITestLib_startServer(JNIEnv* env, jobject o, jstring inputName, jstring streamName, jstring description) {
Run Code Online (Sandbox Code Playgroud)

你可以看到约定是Java_(包名)_(classname)_(methodname)

因为上面的一个用于类似的

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

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

干杯,希望我帮忙:)


Bri*_*ian 5

你有没有尝试过包装你的C代码extern "C".有关更多信息,请参阅C++ Faq Lite,以及其他可能允许您在C++中使用C代码的机制.