5#ifndef WPIUTIL_WPI_JNI_UTIL_H_
6#define WPIUTIL_WPI_JNI_UTIL_H_
54 JClass(JNIEnv* env,
const char* name) {
55 jclass local = env->FindClass(name);
59 m_cls =
static_cast<jclass
>(env->NewGlobalRef(local));
60 env->DeleteLocalRef(local);
65 env->DeleteGlobalRef(
m_cls);
70 explicit operator bool()
const {
return m_cls; }
72 operator jclass()
const {
return m_cls; }
89 m_cls =
static_cast<T
>(env->NewGlobalRef(obj));
94 env->DeleteGlobalRef(
m_cls);
99 explicit operator bool()
const {
return m_cls; }
101 operator T()
const {
return m_cls; }
129 m_env->DeleteLocalRef(m_obj);
132 operator T() {
return m_obj; }
154 jsize
size = env->GetStringLength(
str);
155 const jchar* chars = env->GetStringCritical(
str,
nullptr);
158 env->ReleaseStringCritical(
str, chars);
161 errs() <<
"JStringRef was passed a null pointer at \n"
181template <
typename C,
typename T>
184 operator std::span<const T>()
const {
185 return static_cast<const C*
>(
this)->
array();
199 auto arr =
static_cast<const C*
>(
this)->
array();
203 return {
reinterpret_cast<const char*
>(arr.data()), arr.size()};
206 std::span<const uint8_t>
uarray()
const {
207 auto arr =
static_cast<const C*
>(
this)->
array();
211 return {
reinterpret_cast<const uint8_t*
>(arr.data()), arr.size()};
222 template <
typename U,
224 std::is_integral_v<U>>>
225 operator std::span<const U>()
const {
226 auto arr =
static_cast<const C*
>(
this)->
array();
230 return {
reinterpret_cast<const U*
>(arr.data()), arr.size()};
240 explicit operator bool()
const {
return this->
m_elements !=
nullptr; }
261 oth.m_jarr =
nullptr;
262 oth.m_elements =
nullptr;
266 this->
m_env = oth.m_env;
267 this->
m_jarr = oth.m_jarr;
268 this->
m_size = oth.m_size;
270 oth.m_jarr =
nullptr;
271 oth.m_elements =
nullptr;
291 :
JArrayRefBase(env, jarr, jarr ? env->GetArrayLength(jarr) : 0) {}
303#define WPI_JNI_JARRAYREF(T, F) \
304 class J##F##ArrayRef : public detail::JArrayRefBase<T> { \
306 J##F##ArrayRef(JNIEnv* env, jobject bb, int len) \
307 : detail::JArrayRefBase<T>( \
309 static_cast<T*>(bb ? env->GetDirectBufferAddress(bb) : nullptr), \
312 errs() << "JArrayRef was passed a null pointer at \n" \
313 << GetJavaStackTrace(env); \
316 J##F##ArrayRef(JNIEnv* env, T##Array jarr, int len) \
317 : detail::JArrayRefBase<T>(env, jarr, len) { \
319 m_elements = env->Get##F##ArrayElements(jarr, nullptr); \
321 errs() << "JArrayRef was passed a null pointer at \n" \
322 << GetJavaStackTrace(env); \
325 J##F##ArrayRef(JNIEnv* env, T##Array jarr) \
326 : detail::JArrayRefBase<T>(env, jarr) { \
328 m_elements = env->Get##F##ArrayElements(jarr, nullptr); \
330 errs() << "JArrayRef was passed a null pointer at \n" \
331 << GetJavaStackTrace(env); \
334 ~J##F##ArrayRef() { \
335 if (m_jarr && m_elements) { \
336 m_env->Release##F##ArrayElements(static_cast<T##Array>(m_jarr), \
337 m_elements, JNI_ABORT); \
342 class CriticalJ##F##ArrayRef : public detail::JArrayRefBase<T> { \
344 CriticalJ##F##ArrayRef(JNIEnv* env, T##Array jarr, int len) \
345 : detail::JArrayRefBase<T>(env, jarr, len) { \
348 static_cast<T*>(env->GetPrimitiveArrayCritical(jarr, nullptr)); \
350 errs() << "JArrayRef was passed a null pointer at \n" \
351 << GetJavaStackTrace(env); \
354 CriticalJ##F##ArrayRef(JNIEnv* env, T##Array jarr) \
355 : detail::JArrayRefBase<T>(env, jarr) { \
358 static_cast<T*>(env->GetPrimitiveArrayCritical(jarr, nullptr)); \
360 errs() << "JArrayRef was passed a null pointer at \n" \
361 << GetJavaStackTrace(env); \
364 ~CriticalJ##F##ArrayRef() { \
365 if (m_jarr && m_elements) { \
366 m_env->ReleasePrimitiveArrayCritical(m_jarr, m_elements, JNI_ABORT); \
379#undef WPI_JNI_JARRAYREF
394 return env->NewString(chars.
begin(), chars.
size());
407 bool = (std::is_integral<T>::value &&
sizeof(jint) ==
sizeof(T))>
409 static jintArray
ToJava(JNIEnv* env, std::span<const T> arr) {
410 jintArray jarr = env->NewIntArray(arr.size());
415 static_cast<jint*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
419 for (
size_t i = 0; i < arr.size(); ++i) {
420 elements[i] =
static_cast<jint
>(arr[i]);
422 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
432 static jintArray
ToJava(JNIEnv* env, std::span<const T> arr) {
433 jintArray jarr = env->NewIntArray(arr.size());
437 env->SetIntArrayRegion(jarr, 0, arr.size(),
438 reinterpret_cast<const jint*
>(arr.data()));
463inline jintArray
MakeJIntArray(JNIEnv* env, std::span<T> arr) {
502 jbyteArray jarr = env->NewByteArray(str.size());
506 env->SetByteArrayRegion(jarr, 0, str.size(),
507 reinterpret_cast<const jbyte*
>(str.data()));
518 jbooleanArray jarr = env->NewBooleanArray(arr.size());
523 static_cast<jboolean*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
527 for (
size_t i = 0; i < arr.size(); ++i) {
528 elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
530 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
541 jbooleanArray jarr = env->NewBooleanArray(arr.size());
546 static_cast<jboolean*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
550 for (
size_t i = 0; i < arr.size(); ++i) {
551 elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
553 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
559#define WPI_JNI_MAKEJARRAY(T, F) \
560 inline T##Array MakeJ##F##Array(JNIEnv* env, std::span<const T> arr) { \
561 T##Array jarr = env->New##F##Array(arr.size()); \
565 env->Set##F##ArrayRegion(jarr, 0, arr.size(), arr.data()); \
575#undef WPI_JNI_MAKEJARRAY
578 sizeof(
typename T::value_type) ==
sizeof(jlong) &&
579 std::is_integral_v<typename T::value_type>>>
581 jlongArray jarr = env->NewLongArray(arr.size());
585 env->SetLongArrayRegion(jarr, 0, arr.size(),
586 reinterpret_cast<const jlong*
>(arr.data()));
597 std::span<const std::string> arr) {
598 static JClass stringCls{env,
"java/lang/String"};
602 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
606 for (
size_t i = 0; i < arr.size(); ++i) {
608 env->SetObjectArrayElement(jarr, i, elem.obj());
620 std::span<std::string_view> arr) {
621 static JClass stringCls{env,
"java/lang/String"};
625 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
629 for (
size_t i = 0; i < arr.size(); ++i) {
631 env->SetObjectArrayElement(jarr, i, elem.obj());
656 void Main()
override;
667 void SetFunc(JNIEnv* env, jobject func, jmethodID mid);
669 template <
typename... Args>
670 void Send(Args&&... args);
675 auto thr = this->GetThread();
681 env->DeleteGlobalRef(thr->m_func);
684 thr->m_func = env->NewGlobalRef(func);
689template <
typename... Args>
691 auto thr = this->GetThread();
695 thr->m_queue.emplace(std::forward<Args>(args)...);
696 thr->m_cond.notify_one();
702 JavaVMAttachArgs args;
703 args.version = JNI_VERSION_1_2;
704 args.name =
const_cast<char*
>(T::GetName());
705 args.group =
nullptr;
706 jint rs = T::GetJVM()->AttachCurrentThreadAsDaemon(
707 reinterpret_cast<void**
>(&env), &args);
712 std::unique_lock lock(m_mutex);
714 m_cond.wait(lock, [&] {
return !(m_active && m_queue.empty()); });
718 while (!m_queue.empty()) {
722 auto item = std::move(m_queue.front());
727 item.CallJava(env, func, mid);
728 if (env->ExceptionCheck()) {
729 env->ExceptionDescribe();
730 env->ExceptionClear();
736 JavaVM* jvm = T::GetJVM();
738 jvm->DetachCurrentThread();
753 static JClass throwableCls(env,
"java/lang/Throwable");
757 static jmethodID constructorId =
nullptr;
758 if (!constructorId) {
759 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
761 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
766 static jmethodID getStackTraceId =
nullptr;
767 if (!getStackTraceId) {
768 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
769 "()[Ljava/lang/StackTraceElement;");
774 env,
static_cast<jobjectArray
>(
775 env->CallObjectMethod(throwable, getStackTraceId)));
782 jsize stackTraceLength = env->GetArrayLength(stackTrace);
785 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
786 if (!stackTraceElementCls) {
789 static jmethodID toStringId =
nullptr;
791 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
792 "()Ljava/lang/String;");
795 bool foundFirst =
false;
798 for (jsize i = 0; i < stackTraceLength; i++) {
801 env, env->GetObjectArrayElement(stackTrace, i));
805 env,
static_cast<jstring
>(
806 env->CallObjectMethod(curStackTraceElement, toStringId)));
808 if (!stackElementString) {
820 oss <<
"\tat " << elem <<
'\n';
829 static JClass throwableCls(env,
"java/lang/Throwable");
833 static jmethodID constructorId =
nullptr;
834 if (!constructorId) {
835 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
837 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
842 static jmethodID getStackTraceId =
nullptr;
843 if (!getStackTraceId) {
844 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
845 "()[Ljava/lang/StackTraceElement;");
850 env,
static_cast<jobjectArray
>(
851 env->CallObjectMethod(throwable, getStackTraceId)));
858 jsize stackTraceLength = env->GetArrayLength(stackTrace);
861 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
862 if (!stackTraceElementCls) {
865 static jmethodID toStringId =
nullptr;
867 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
868 "()Ljava/lang/String;");
871 bool haveLoc =
false;
874 for (jsize i = 0; i < stackTraceLength; i++) {
877 env, env->GetObjectArrayElement(stackTrace, i));
881 env,
static_cast<jstring
>(
882 env->CallObjectMethod(curStackTraceElement, toStringId)));
884 if (!stackElementString) {
897 }
else if (i > 1 && !haveLoc && !excludeFuncPrefix.empty() &&
921 env->GetMethodID(
m_cls,
"<init>",
"(Ljava/lang/String;)V");
925 void Throw(JNIEnv* env, jstring msg) {
927 env->Throw(
static_cast<jthrowable
>(
exception));
934 explicit operator bool()
const {
return m_constructor; }
937 jmethodID m_constructor =
nullptr;
This file defines the SmallString class.
you may not use this file except in compliance with the License You may obtain a copy of the License at software distributed under the License is distributed on an AS IS WITHOUT WARRANTIES OR CONDITIONS OF ANY either express or implied See the License for the specific language governing permissions and limitations under the License LLVM Exceptions to the Apache License As an exception
Definition: ThirdPartyNotices.txt:292
Definition: SafeThread.h:33
Definition: SafeThread.h:124
std::string_view str() const
Explicit conversion to std::string_view.
Definition: SmallString.h:181
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1186
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:557
void pop_back()
Definition: SmallVector.h:415
void push_back(const T &Elt)
Definition: SmallVector.h:403
size_t size() const
Definition: SmallVector.h:78
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:271
iterator begin()
Definition: SmallVector.h:252
This class is a wrapper around std::array that does compile time size checking.
Definition: array.h:25
void SetJoinAtExit(bool joinAtExit)
Definition: SafeThread.h:106
Definition: jni_util.h:664
JCallbackManager()
Definition: jni_util.h:666
void SetFunc(JNIEnv *env, jobject func, jmethodID mid)
Definition: jni_util.h:674
void Send(Args &&... args)
Definition: jni_util.h:690
Generic callback thread implementation.
Definition: jni_util.h:654
jmethodID m_mid
Definition: jni_util.h:660
jobject m_func
Definition: jni_util.h:659
std::queue< T > m_queue
Definition: jni_util.h:658
void Main() override
Definition: jni_util.h:700
Finds a class and keeps it as a global reference.
Definition: jni_util.h:50
JClass(JNIEnv *env, const char *name)
Definition: jni_util.h:54
jclass m_cls
Definition: jni_util.h:75
void free(JNIEnv *env)
Definition: jni_util.h:63
Finds an exception class and keep it as a global reference.
Definition: jni_util.h:915
void Throw(JNIEnv *env, std::string_view msg)
Definition: jni_util.h:930
JException(JNIEnv *env, const char *name)
Definition: jni_util.h:918
void Throw(JNIEnv *env, jstring msg)
Definition: jni_util.h:925
Definition: jni_util.h:84
JGlobal(JNIEnv *env, T obj)
Definition: jni_util.h:88
void free(JNIEnv *env)
Definition: jni_util.h:92
T m_cls
Definition: jni_util.h:104
Container class for cleaning up Java local references.
Definition: jni_util.h:113
JLocal & operator=(const JLocal &)=delete
~JLocal()
Definition: jni_util.h:127
JLocal(JLocal &&oth)
Definition: jni_util.h:117
JLocal & operator=(JLocal &&oth)
Definition: jni_util.h:121
T obj()
Definition: jni_util.h:133
JLocal(JNIEnv *env, T obj)
Definition: jni_util.h:115
JLocal(const JLocal &)=delete
Definition: jni_util.h:743
static JSingletonCallbackManager< T > & GetInstance()
Definition: jni_util.h:745
Java string (jstring) reference.
Definition: jni_util.h:150
std::string_view str() const
Definition: jni_util.h:170
const char * c_str() const
Definition: jni_util.h:171
size_t size() const
Definition: jni_util.h:172
JStringRef(JNIEnv *env, jstring str)
Definition: jni_util.h:152
Base class for J*ArrayRef and CriticalJ*ArrayRef.
Definition: jni_util.h:238
JArrayRefBase(JNIEnv *env, jarray jarr)
Definition: jni_util.h:290
size_t m_size
Definition: jni_util.h:295
size_t size() const
Definition: jni_util.h:249
std::span< const T > array() const
Definition: jni_util.h:242
JArrayRefBase & operator=(const JArrayRefBase &)=delete
T & operator[](size_t i)
Definition: jni_util.h:250
T * m_elements
Definition: jni_util.h:296
JArrayRefBase(JNIEnv *env, T *elements, size_t size)
Definition: jni_util.h:276
JArrayRefBase & operator=(JArrayRefBase &&oth)
Definition: jni_util.h:265
JArrayRefBase(JNIEnv *env, jarray jarr, size_t size)
Definition: jni_util.h:283
JNIEnv * m_env
Definition: jni_util.h:293
jarray m_jarr
Definition: jni_util.h:294
const T & operator[](size_t i) const
Definition: jni_util.h:251
JArrayRefBase(const JArrayRefBase &)=delete
JArrayRefBase(JArrayRefBase &&oth)
Definition: jni_util.h:256
std::string_view str() const
Definition: jni_util.h:198
std::span< const uint8_t > uarray() const
Definition: jni_util.h:206
Definition: jni_util.h:182
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:554
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:572
typename std::enable_if< B, T >::type enable_if_t
Definition: core.h:298
basic_string_view< char > string_view
Definition: core.h:520
#define WPI_JNI_MAKEJARRAY(T, F)
Definition: jni_util.h:559
#define WPI_JNI_JARRAYREF(T, F)
Definition: jni_util.h:303
::uint8_t uint8_t
Definition: Meta.h:52
Java Native Interface (JNI) utility functions.
Definition: jni_util.h:27
jintArray MakeJIntArray(JNIEnv *env, std::span< const T > arr)
Convert a span to a jintArray.
Definition: jni_util.h:452
jstring MakeJString(JNIEnv *env, std::string_view str)
Convert a UTF8 string into a jstring.
Definition: jni_util.h:391
jlongArray MakeJLongArray(JNIEnv *env, const T &arr)
Definition: jni_util.h:580
std::string GetJavaStackTrace(JNIEnv *env, std::string *func=nullptr, std::string_view excludeFuncPrefix={})
Gets a Java stack trace.
Definition: jni_util.h:826
jbooleanArray MakeJBooleanArray(JNIEnv *env, std::span< const int > arr)
Convert an array of integers into a jbooleanArray.
Definition: jni_util.h:517
jobjectArray MakeJStringArray(JNIEnv *env, std::span< const std::string > arr)
Convert an array of std::string into a jarray of jstring.
Definition: jni_util.h:596
jbyteArray MakeJByteArray(JNIEnv *env, std::span< const uint8_t > str)
Convert a span into a jbyteArray.
Definition: jni_util.h:501
bool convertUTF8ToUTF16String(std::string_view SrcUTF8, SmallVectorImpl< UTF16 > &DstUTF16)
Converts a UTF-8 string into a UTF-16 string with native endianness.
bool Boolean
Definition: ConvertUTF.h:115
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
bool convertUTF16ToUTF8String(std::span< const char > SrcBytes, SmallVectorImpl< char > &Out)
Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string.
constexpr bool starts_with(std::string_view str, std::string_view prefix) noexcept
Checks if str starts with the given prefix.
Definition: StringExtras.h:232
Definition: jni_util.h:78
const char * name
Definition: jni_util.h:79
JClass * cls
Definition: jni_util.h:80
Definition: jni_util.h:940
JException * cls
Definition: jni_util.h:942
const char * name
Definition: jni_util.h:941
Fast path (use SetIntArrayRegion).
Definition: jni_util.h:431
static jintArray ToJava(JNIEnv *env, std::span< const T > arr)
Definition: jni_util.h:432
Slow path (get primitive array and set individual elements).
Definition: jni_util.h:408
static jintArray ToJava(JNIEnv *env, std::span< const T > arr)
Definition: jni_util.h:409