Reputation: 1260
There are lots of examples that Android C/C++ native calls Java APIs. However, all of these examples I have read are the Android Java APIs call native first and then the native calls other Java APIs by using the passed JNI-ENV.
Without the passed JNI-ENV, how can the C/C++ get it? Is it possible that C/C++ native calls Java APIs without JNI-ENV?
Can you give an example or a link for it if it is possible?
Thanks!
Upvotes: 1
Views: 1609
Reputation: 2086
You need to include jni.h
first. This brings a ton of useful calls; with newer android releases you'll also need JniInvocation.h
. To enable this:
LOCAL_C_INCLUDES += ${JNI_H_INCLUDE}
That certainly works with source tree, not sure about NDK, but should be fine, too.
Second, pretty important thing is to have proper signal chain lib selected. Art or Dalvik will load libsigchain.so, which is a stub and abort()
s every time any of its methods are being called. On Android it's done with a little hack: local symbols are being exported to global symbol table, so that Art picks exec's symbols instead of loading shared lib. Here's how it's done:
# 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
Link your executable now. Double check that the required symbols are indeed exported:
% readelf -a <output_binary> | grep InitializeSignalChain
654: 0002cab1 211 FUNC GLOBAL PROTECTED 12 InitializeSignalChain
Done? things get simpler now:
Initialize the JNI (so that your code uses proper VM)
JniInvocation invocation;
if (invocation.Init(nullptr)) return;
Create 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;
At this point your vm
and env
are ready to use. have fun.
Check for exceptions, if any
if (env->ExceptionCheck()) {
// ...
}
When you're done, clean up
vm->DetachCurrentThread();
vm->DestroyJavaVM();
More interesting stuff can be found here and DalvikVM Main is probably the best source of knowledge. Good luck!
Upvotes: 3