【问题标题】:Calling a Java function from the Native code using the NDK使用 NDK 从 Native 代码调用 Java 函数
【发布时间】:2012-07-24 16:50:51
【问题描述】:

我前几天问过这个问题,但不是太具体,所以我想重新澄清一下。

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

无论如何,我想知道是否可以在我的 Java 代码中编写 C 代码调用的函数。现在,据我所知,您可以做到,所以如果没有人回答“是的,您可以,LINK,我将不胜感激。” .

谁能解释一下这个过程?我知道这涉及在 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 方法吗?

【问题讨论】:

  • 我知道你说你只是不想要一个链接,但这很容易解释:codeproject.com/Articles/22881/…。这绝对不是几行代码就能涵盖所有你需要知道的主题。
  • 是的,我知道,感谢您的意见。
  • 我开始查看您发送的内容,但仍有一些不确定。如果您有时间,请查看我编辑的内容,如果您能提供帮助,请告诉我。
  • 我认为你不能直接在 Android 上创建虚拟机。它有自己的虚拟机,Android 平台控制它的调用方式。相反,我认为您希望 this method 从 C 中调用 Java 代码。

标签: android c android-ndk


【解决方案1】:

每个可通过 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。

【讨论】:

  • 您说每个可以从 Java 调用的 C 函数......但这不正是 NDK 的用途吗?我读到的关于 NDK 的所有内容都没有提到使用 JNIEnv*。我只是在我想返回并从我的 C 代码中调用 Java 函数时才遇到这种情况,而这些 C 代码已经从 Java 中调用过。我知道这听起来很疯狂,但这是我被要求做的。
  • 我从来没有说过每个 C 函数都可以从 Java 中调用。事实并非如此。我说过每个可调用函数都有一个 JNIEnv* 参数。
  • 好的,我知道,every C function that IS callable 我说过。但我过去从未在任何地方读到这是真的。我试图理解你的措辞......你的意思是Java中每个可以从C调用的函数吗?我想做的是,从 Android 开始,调用一个 C 函数,然后在该 C 函数中,调用一个不同的 Android 函数。
  • 您的意思是,如果可以从 Java 调用 C 函数,则它需要将其作为第一个参数。而且我看不到哪里。 JNIEnv* 唯一发挥作用的时候是当需要从 C 调用 Java 函数时,对吗?
  • Java 中的每个函数都可以从 C 中调用,是的。但不是反过来。以防万一,这里是another "intro to JNI" post that I wrote the other day。它专门处理 Java 的可调用性问题。也许它有帮助......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-29
  • 2014-05-16
  • 2011-11-08
相关资源
最近更新 更多