使用NDK从本地代码调用Java函数

3

我前几天问了这个问题,但没有太具体,所以我想再澄清一下。

我正在创建一个使用现有的C库并使用NDK的Android应用程序。我遇到的问题是C代码使用了很多Java不支持的东西(将函数指针作为参数是一个大问题)。

无论如何,我想知道是否可以编写在C代码中调用的Java代码。从我所了解的情况来看,似乎可以这样做,因此我希望没有人只回答“是的,你可以,链接。”我一直在研究它,但实际上需要做什么非常超出了我的理解范围。

有人能尝试解释一下这个过程吗?我知道它涉及在C代码中创建JVM;任何可以帮助新手入门的信息都将不胜感激。

谢谢

编辑:

所以,我不知道这三个步骤该怎么做。

To call a specific Java function from C, you need to do the following:

Obtain the class reference using the FindClass(,,) method.
Obtain the method IDs of the functions of the class that you want to call using the 
GetStaticMethodID and GetMethodID function calls.

Call the functions using CallStaticVoidMethod, CallStaticIntMethod, and CallStaticObjectMethod.

这段文字并没有详细解释,而且我对C语言一无所知。FindClass是C语言中的一个方法吗?

1
我知道你说你不想要一个链接,但这是关于如何调用Java函数使用JNI从C ++中的最简单的解释:http://www.codeproject.com/Articles/22881/How-to-Call-Java-Functions-from-C-Using-JNI。这绝对不是一个只需要几行代码就能涵盖你所需了解的主题。 - AlcoJaguar
我已经开始查看你发送的内容,但仍然不确定一些事情。如果你有时间,请看看我编辑的内容,让我知道你是否能够帮忙。 - JuiCe
我认为你不能在Android上创建一个虚拟机。它有自己的虚拟机,并且Android平台控制它如何被调用。相反,我认为你想要使用这个方法从C中调用Java代码。链接 - mpontillo
1个回答

4

每个可通过JNI从Java中调用的C函数都具有类型为JNIEnv*的第一个参数。在C端,这是指向指向一堆函数指针的结构体指针。这些函数是你与Java世界交互的接口,其中包括FindClassGetMethodID等函数。

因此,当你想从C端调用FindClass时,以下是如何操作:

void Java_com_mypackage_MyClass_MyMethod(JNIEnv *jniEnv, jobject thiz)
{
    jclass *clazz = (*(*jniEnv)->FindClass)(jniEnv, "com/mypackage/SomeClass");
    jmethodID MethodID = (*(*jniEnv)->GetStaticMethodID)(jniEnv, clazz, "SomeMethod", "(I)I");
    int result = (*(*jniEnv)->CallStaticIntMethod)(jniEnv, clazz, MethodID, 18);

等等。这行代码取消引用了jniEnv参数,获取函数指针并通过它调用函数。当然,类名和方法名是完全虚假的。我怎么知道你的。

注意:我在谈论函数指针,但不是你所说的那种;这些是JNI提供的函数指针,而不是你的函数。

调用语法的冗长与C的限制有关;在C++中,您可以写成:

jclass *cl = jniEnv->FindClass("com/mypackage/SomeClass");

由于C++通过虚函数本地支持这种类型的函数表指针。

你可能可以沿途走捷径。如果你在调用与你的C入口点相同类中的方法,并且它恰好是静态的,那么你的第二个参数已经是一个类对象指针。如果你有一个指向想要调用方法的对象的this指针,你可以使用GetObjectClass。


您是在说如果一个C函数可以从Java调用,它需要作为第一个参数。但我没有看到这一点。只有在需要从C中调用Java函数时,JNIEnv*才会发挥作用,对吗? - JuiCe
哦,关于JNIEnv。来自这个文档:"JNI接口指针是本地方法的第一个参数。 JNI接口指针的类型为JNIEnv。第二个参数因本地方法是静态的还是非静态的而异。对于非静态本地方法,第二个参数是对该对象的引用。对于静态本地方法,第二个参数是对其Java类的引用。" - Seva Alekseyev
我没有其他要说的了。感谢您的帮助。在开始编码之前,我还有很多阅读要做。 - JuiCe
我有一个简单的问题,因为我是ndk的新手。在c文件中,我是否可以只调用MyMethod()而不是调用void Java_com_mypackage_MyClass_MyMethod。这是否可能?如果不行,请告诉我为什么不行。 - AndroidOptimist
@AndroidOptimist:请将您的问题作为一个单独的问题提出。JuiCe的问题早已得到解答。StackOverflow不是一个论坛。 - Seva Alekseyev
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接