From 18034f78069e38f27f641a4942f925c193b9560e Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 28 Jan 2018 13:20:43 +0300 Subject: [PATCH] Add td::jni::get_jni_env wrapper. GitOrigin-RevId: 5cc7cc927d0195bcdc7f8adbeea052266dff6af5 --- README.md | 4 ++-- td/tl/tl_jni_object.cpp | 16 ++++++++++++++++ td/tl/tl_jni_object.h | 31 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 737bb1a6e..320357995 100644 --- a/README.md +++ b/README.md @@ -23,10 +23,10 @@ TDLib (Telegram Database library) is a cross-platform library for building [Tele * **Easy to use**: `TDLib` takes care of all network implementation details, encryption and local data storage. * **High-performance**: in the [Telegram Bot API](https://core.telegram.org/bots/api), each `TDLib` instance handles more than 18000 active bots simultaneously. * **Well-documented**: all `TDLib` API methods and public interfaces are fully documented. -* **Consistent**: `TDLib` guarantees that all updates will be delivered in the right order. +* **Consistent**: `TDLib` guarantees that all updates are delivered in the right order. * **Reliable**: `TDLib` remains stable on slow and unstable Internet connections. * **Secure**: all local data is encrypted using a user-provided encryption key. -* **Fully-asynchronous**: requests to `TDLib` don't block each other or anything else, responses will be sent when they are available. +* **Fully-asynchronous**: requests to `TDLib` don't block each other or anything else, responses are sent when they are available. ## Examples and documentation diff --git a/td/tl/tl_jni_object.cpp b/td/tl/tl_jni_object.cpp index 7c081d144..ab685f82f 100644 --- a/td/tl/tl_jni_object.cpp +++ b/td/tl/tl_jni_object.cpp @@ -76,6 +76,22 @@ void register_native_method(JNIEnv *env, jclass clazz, std::string name, std::st } } +std::unique_ptr get_jni_env(JavaVM *java_vm, jint jni_version) { + JNIEnv *env = nullptr; + if (java_vm->GetEnv(reinterpret_cast(&env), jni_version) == JNI_EDETACHED) { +#ifdef JDK1_2 // if not Android JNI + auto p_env = reinterpret_cast(&env); +#else + auto p_env = &env; +#endif + java_vm->AttachCurrentThread(p_env, nullptr); + } else { + java_vm = nullptr; + } + + return std::unique_ptr(env, JvmThreadDetacher(java_vm)); +} + void init_vars(JNIEnv *env, const char *td_api_java_package) { BooleanClass = get_jclass(env, "java/lang/Boolean"); IntegerClass = get_jclass(env, "java/lang/Integer"); diff --git a/td/tl/tl_jni_object.h b/td/tl/tl_jni_object.h index 4c65e90e5..d32ed75b7 100644 --- a/td/tl/tl_jni_object.h +++ b/td/tl/tl_jni_object.h @@ -39,6 +39,37 @@ jfieldID get_field_id(JNIEnv *env, jclass clazz, const char *name, const char *s void register_native_method(JNIEnv *env, jclass clazz, std::string name, std::string signature, void *function_ptr); +class JvmThreadDetacher { + JavaVM *java_vm_; + + void detach() { + if (java_vm_ != nullptr) { + java_vm_->DetachCurrentThread(); + java_vm_ = nullptr; + } + } + + public: + explicit JvmThreadDetacher(JavaVM *java_vm): java_vm_(java_vm) { + } + + JvmThreadDetacher(const JvmThreadDetacher &other) = delete; + JvmThreadDetacher &operator=(const JvmThreadDetacher &other) = delete; + JvmThreadDetacher(JvmThreadDetacher &&other): java_vm_(other.java_vm_) { + other.java_vm_ = nullptr; + } + JvmThreadDetacher &operator=(JvmThreadDetacher &&other) = delete; + ~JvmThreadDetacher() { + detach(); + } + + void operator()(JNIEnv *env) { + detach(); + } +}; + +std::unique_ptr get_jni_env(JavaVM *java_vm, jint jni_version); + std::string fetch_string(JNIEnv *env, jobject o, jfieldID id); inline jobject fetch_object(JNIEnv *env, const jobject &o, const jfieldID &id) {