所以我在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 ++交互的区别是什么?非常感谢任何帮助。
谢谢,皮特
答案 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 ++,不是吗?所以,你已经完成了!
说真的,你想在那段代码中改变什么?为什么呢?