JNI在C与C++;? p>所以我在C中使用了Java 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); } < JNI与C和C++交互有什么区别?非常感谢您的帮助

JNI在C与C++;? p>所以我在C中使用了Java 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); } < JNI与C和C++交互有什么区别?非常感谢您的帮助,java,c++,c,java-native-interface,Java,C++,C,Java Native Interface,谢谢,Pete您是否尝试过将您的C代码包装到外部“C”中。请参阅更多信息,以及其他可能的机制,让您使用C++代码。 自从我接触标准C++以来,已经有一段时间了,但我还是要尝试它。 “(*env)->”在我看来很奇怪。这不应该是“env->”吗 也许我错了,这本书应该有用,但为什么要把事情弄得更复杂呢?我以前有这本书。虽然它有点过时了,但大部分至今仍然有效 如果我没记错的话,在C语言中,Java构造只是指针。因此,在您的代码中,“(*env)->”是取消对指针的引用,以允许您访问底层方法 对于C+

谢谢,Pete

您是否尝试过将您的C代码包装到外部“C”中。请参阅更多信息,以及其他可能的机制,让您使用C++代码。

自从我接触标准C++以来,已经有一段时间了,但我还是要尝试它。 “
(*env)->
”在我看来很奇怪。这不应该是“
env->
”吗

也许我错了,这本书应该有用,但为什么要把事情弄得更复杂呢?

我以前有这本书。虽然它有点过时了,但大部分至今仍然有效

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

对于C++,“<代码> Env”实际上是一个对象——与C指针不同的实体。(JNI实际上可以提供真正的对象供C++代码操作,因为C++实际上支持对象。)因此“<代码> EnV-><代码>”在C++中有不同的含义,它意味着调用由“<代码> Env”指向的对象中包含的方法。 另一个不同点,我相信,许多C-JNI函数需要一个参数是“<代码> JNENV*Env< /Calp>”。所以在C中,你可能不得不说<代码>(*Env)-Foo(Env,bar)< /C>。C++中,第二个引用“<代码> Env< /C>”不是必须的,所以你可以说“<代码> Env- > Foo(bar)< /C> >


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

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

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

C++风格的JNI看起来像 env->SomeJNICall(参数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(包名)u(类名)u(方法名)

因为上面的一个是在一个类中使用的

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调用)


欢呼,希望我帮助:“< P”>上面有什么不对?它看起来像是C++的C++代码。由于构建的例子很好。但我想这可能是问题所在。JNI希望C代码,所以他可能会链接错误。YARP。名字可能在C++编译器中被修改。为什么你要把C++代码包成C,当你可以使用更简洁的C++语法时,为什么使用丑陋的C语法?@ RuStux:当移植代码时,你可以选择做一个语义端口(保留语义,但是使用语言特定的特征和构造)或者逐行端口。(尽可能少地更改代码,主要是逐行更改,而不是整体更改)。语义端口更易于维护和使用。逐行端口更易于操作,并且更易于利用与原始代码相关的任何现有知识库。请注意,如果试图将构造移植到不真正支持它的语言,逐行端口可能会引入奇怪的错误。我还将注意,逐行端口如果说ort非常简单(就像这里的例子),那么它是一种很好的方法,可以提供一个原型来验证被移植的库在移植后是否可用。x->y是(*x).y的缩写。因此,(*env)->y相当于(**env).y,这与(*env)不同y:有一个额外的引用出现。我知道,引用引用语法。让我更清楚地说:我只是不相信C++版本的JNIENV实际上需要双重撤销。@ JieleluBee看到。所以JNI实际上可以处理C和C++两个?我不知道(但是这并不奇怪,因为我从来没有使用JNI:P)。(哈哈,TY,用于修复我的标记!),界面的行为方式相同,C与C++代码基本上是同构的,实际上,唯一的区别是语法。

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...
}