JNI调用在C和C++中有什么不同?

vaqhlq81  于 2023-04-05  发布在  其他
关注(0)|答案(4)|浏览(199)

所以我有下面的C代码,利用Java本机接口,但我想转换为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++交互的区别是什么?
谢谢你,皮特

xqkwcwgp

xqkwcwgp1#

我曾经有一本书Essential JNI。虽然它有点过时(1998年),但它的大部分内容今天仍然有效。
如果我没记错的话,在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代码中查找它们)将让你走得很远。

8dtrkrch

8dtrkrch2#

C和CPP中JNI调用的主要区别是:
C风格的JNI看起来像(*env)-〉SomeJNICall(env,param 1...)
C++风格的JNI看起来像env-〉SomeJNICall(param 1...)
所以要将其转换为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_(包名)(类名)(方法名)
因为上面的一个是在类中使用的,如

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调用)
谢谢,希望我能帮上忙:)

628mspwn

628mspwn3#

你有没有试过将你的C代码 Package 在一个extern "C"中。请参阅C++ Faq Lite以获得更多信息,以及其他可能的机制,让你在C++中使用你的C代码。

cygmwpex

cygmwpex4#

我已经有一段时间没有接触标准C++了,但无论如何我都会尝试一下。
(*env)->“在我看来很奇怪。它不应该是“env->“吗?
也许我错了,它应该工作,但为什么让事情变得更复杂呢?

相关问题