Android C/C++原生调用Java API的例子有很多。 但是,我读过的所有这些示例都是 Android Java API 调用 native 首先,然后 native 使用传递的 JNI-ENV 调用其他 Java API。
没有传入的JNI-ENV,C/C++怎么获取呢? C/C++ native 是否可以在没有 JNI-ENV 的情况下调用 Java API?
如果可能的话,你能举个例子或链接吗?
谢谢!
最佳答案
您需要先包含jni.h
。这会带来大量有用的调用;对于较新的 android 版本,您还需要 JniInvocation.h
。要启用此功能:
LOCAL_C_INCLUDES += ${JNI_H_INCLUDE}
这当然适用于源代码树,不确定 NDK,但也应该没问题。
其次,非常重要的是选择合适的信号链库。 Art 或 Dalvik 将加载 libsigchain.so,这是一个 stub 和 abort()
每次调用其任何方法时。在 Android 上,它通过一个小 hack 完成:本地符号被导出到全局符号表,因此 Art 选择 exec 的符号而不是加载共享库。这是如何完成的:
# Enable native helper calls
LOCAL_SHARED_LIBRARIES += libnativehelper
# Include all of the Android's libsigchain symbols
LOCAL_WHOLE_STATIC_LIBRARIES += libsigchain
# Export only libsigchain symbols to global symbol table.
LOCAL_LDFLAGS += \
-Wl,--export-dynamic \
-Wl,--version-script,art/sigchainlib/version-script.txt
现在链接您的可执行文件。仔细检查是否确实导出了所需的符号:
% readelf -a <output_binary> | grep InitializeSignalChain
654: 0002cab1 211 FUNC GLOBAL PROTECTED 12 InitializeSignalChain
完成了吗?现在事情变得简单了:
初始化 JNI(以便您的代码使用正确的 VM)
JniInvocation invocation; if (invocation.Init(nullptr)) return;
创建 JavaVM:
JavaVM* vm; JNIEnv* env; JavaVMInitArgs* args; args.version = JNI_VERSION_1_4; // _5, _6 args.options = nullptr; args.nOptions = 0; args.ignoreUnrecognized = JNI_FALSE; if (JNI_CreateJavaVM(&vm, &env, &args) < 0) return;
此时您的
vm
和env
已经可以使用了。玩得开心。检查异常情况,如果有的话
if (env->ExceptionCheck()) { // ... }
完成后,清理
vm->DetachCurrentThread(); vm->DestroyJavaVM();
可以找到更多有趣的东西here和 DalvikVM Main可能是最好的知识来源。祝你好运!
关于java - Android C/C++ native 调用 Java API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11573406/