java C 和 C++ 中的 JNI 调用不同?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/935379/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JNI Calls different in C vs C++?
提问by Petey B
So i have the following code in C that utilizes Java Native Interface however i would like to convert this to C++ but am not sure how.
所以我在 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 Program:
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");
}
}
What are the differences in which JNI interacts with C and C++? Any help is greatly appreciated.
JNI 与 C 和 C++ 交互的区别是什么?任何帮助是极大的赞赏。
Thanks, Pete
谢谢,皮特
采纳答案by poundifdef
I used to have the book Essential JNI. And while it is kinda dated, much of it still works today.
我曾经有一本书Essential JNI。虽然它有点过时了,但其中大部分今天仍然有效。
If I recall correctly, in C, Java constructs are simply pointers. Thus, in your code, "(*env)->" is dereferencing pointers to give you access to the underlying methods.
如果我没记错的话,在 C 中,Java 构造只是指针。因此,在您的代码中,“ (*env)->” 正在取消引用指针以让您访问底层方法。
For C++, "env" is actually an object - a different entity than a C pointer. (And JNI can actually provide real objects for your C++ code to manipulate, since C++ actually supports objects.) So "env->" has a different meaning in C++, it means "call the method that is contained in the object pointed to by "env".
对于 C++,“ env”实际上是一个对象——一个不同于 C 指针的实体。(而且JNI实际上可以为你的C++代码提供真实的对象来操作,因为C++实际上支持对象。)所以“ env->”在C++中有不同的含义,它的意思是“调用”指向的对象中包含的方法env。
The other difference, I believe, is that many of the C-JNI functions require that one of your parameters be the "JNIEnv *env". So in C you might have to say (*env)->foo(env, bar). With c++, the second reference to "env" is not necessary, so you can instead say "env->foo(bar)"
我相信,另一个区别是许多 C-JNI 函数要求您的参数之一是“ JNIEnv *env”。所以在 C 中你可能不得不说(*env)->foo(env, bar). 使用 c++,env不需要第二次引用“ ”,因此您可以改为说“ env->foo(bar)”
Unfortunately, I don't have the above book in front of me, so I can't quite confirm this! But I think investigating those two things (specifically looking for them on google or in other JNI code) will get you pretty far.
不幸的是,我面前没有上面的书,所以我不能完全证实这一点!但我认为调查这两件事(特别是在谷歌或其他 JNI 代码中寻找它们)会让你走得很远。
回答by Shark
The main difference between JNI calls in C and CPP is this:
C 和 CPP 中 JNI 调用的主要区别在于:
C-style JNI looks like (*env)->SomeJNICall(env, param1 ...)
C 风格的 JNI 看起来像 (*env)->SomeJNICall(env, param1 ...)
C++ style JNI looks like env->SomeJNICall(param1 ...)
C++ 风格的 JNI 看起来像 env->SomeJNICall(param1 ...)
so to convert it to CPP you need to do
所以要将其转换为 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
Also, make sure that your JNI functions follow the naming convention.
此外,请确保您的 JNI 函数遵循命名约定。
Example:
例子:
JNIEXPORT jint JNICALL Java_com_shark_JNITestLib_JNITestLib_startServer(JNIEnv* env, jobject o, jstring inputName, jstring streamName, jstring description) {
You can see that the convention is Java_(package name) _ (classname) _ (methodname)
可以看到约定是 Java_(package name) _ (classname) _ (methodname)
since the one above was used in a class like
因为上面的那个是在像这样的类中使用的
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...
}
When working with JNI i made it a convention to name the class containing JNI calls to be the same name as the package. Thats why you see JNITestLib twice (and thats why my JNI works right off the bat because I always forget how to properly name the JNI calls)
使用 JNI 时,我约定将包含 JNI 调用的类命名为与包相同的名称。这就是为什么你会看到 JNITestLib 两次(这就是为什么我的 JNI 立即工作,因为我总是忘记如何正确命名 JNI 调用)
Cheers, hope I helped :)
干杯,希望我有所帮助:)
回答by Brian
Have you tried wrapping your C code in an extern "C". See C++ Faq Litefor more information, and for other possible mechanisms to let you use your C code with C++.
您是否尝试过将 C 代码包装在extern "C". 请参阅C++ Faq Lite以获取更多信息,以及其他允许您将 C 代码与 C++ 结合使用的可能机制。
回答by michael aubert
It's been a while since I touched standard C++ but I'm gonna try it anyway.
自从我接触标准 C++ 已经有一段时间了,但无论如何我都会尝试一下。
"(*env)->" looks weird to me. Shouldn't that simply be "env->" ?
” (*env)->“我觉得很奇怪。那不应该只是 " env->" 吗?
Maybe I'm wrong and it is supposed to work, but why make things more complicated anyways?
也许我错了,它应该可以工作,但为什么要让事情变得更复杂呢?

