5#ifndef WPIUTIL_WPI_JNI_UTIL_H_
6#define WPIUTIL_WPI_JNI_UTIL_H_
44 std::string_view excludeFuncPrefix = {});
56 JClass(JNIEnv* env,
const char* name) {
57 jclass local = env->FindClass(name);
61 m_cls =
static_cast<jclass
>(env->NewGlobalRef(local));
62 env->DeleteLocalRef(local);
67 env->DeleteGlobalRef(
m_cls);
72 explicit operator bool()
const {
return m_cls; }
74 operator jclass()
const {
return m_cls; }
91 m_cls =
static_cast<T
>(env->NewGlobalRef(obj));
96 env->DeleteGlobalRef(
m_cls);
101 explicit operator bool()
const {
return m_cls; }
103 operator T()
const {
return m_cls; }
131 m_env->DeleteLocalRef(m_obj);
134 operator T() {
return m_obj; }
156 jsize size = env->GetStringLength(
str);
157 const jchar* chars = env->GetStringCritical(
str,
nullptr);
160 env->ReleaseStringCritical(
str, chars);
163 wpi::print(stderr,
"JStringRef was passed a null pointer at\n",
171 operator std::string_view()
const {
return m_str.
str(); }
172 std::string_view
str()
const {
return m_str.
str(); }
186#define WPI_JNI_ARRAYHELPER(T, F) \
188 struct ArrayHelper<T> { \
189 using jarray_type = T##Array; \
190 static T* GetArrayElements(JNIEnv* env, jarray_type jarr) { \
191 return env->Get##F##ArrayElements(jarr, nullptr); \
193 static void ReleaseArrayElements(JNIEnv* env, jarray_type jarr, T* elems, \
195 env->Release##F##ArrayElements(jarr, elems, mode); \
207#undef WPI_JNI_ARRAYHELPER
211 requires {
typename ArrayHelper<std::remove_cv_t<T>>::jarray_type; };
213template <
typename CvSrc,
typename Dest>
216 using U0 = std::remove_cv_t<Dest>;
217 using U1 = std::conditional_t<std::is_const_v<CvSrc>,
const U0, U0>;
218 using U2 = std::conditional_t<std::is_volatile_v<CvSrc>,
volatile U1, U1>;
224template <
typename CvSrc,
typename Dest>
227template <
typename From,
typename To>
229 !(std::is_const_v<From> && !std::is_const_v<To>) &&
230 !(std::is_volatile_v<From> && !std::is_volatile_v<To>);
247template <JArrayType T,
bool IsCritical,
size_t Size = std::dynamic_extent>
250 using jarray_type =
typename ArrHelper::jarray_type;
257 : m_valid{other.m_valid},
259 m_jarr{other.m_jarr},
260 m_size{other.m_size},
261 m_elements{other.m_elements} {
262 other.m_jarr =
nullptr;
263 other.m_elements =
nullptr;
267 m_valid = other.m_valid;
269 m_jarr = other.m_jarr;
270 m_size = other.m_size;
271 m_elements = other.m_elements;
272 other.m_valid =
false;
273 other.m_jarr =
nullptr;
274 other.m_elements =
nullptr;
279 requires(!IsCritical)
280 : m_valid{Size ==
std::dynamic_extent || size == Size},
284 m_elements{static_cast<
std::remove_cv_t<T>*>(
285 bb ? env->GetDirectBufferAddress(bb) : nullptr)} {
287 wpi::print(stderr,
"JSpan was passed a null pointer at\n",
293 : m_valid{Size ==
std::dynamic_extent || size == Size},
297 m_elements{nullptr} {
299 if constexpr (IsCritical) {
300 m_elements =
static_cast<std::remove_cv_t<T>*
>(
301 env->GetPrimitiveArrayCritical(jarr,
nullptr));
303 m_elements = ArrHelper::GetArrayElements(env, jarr);
306 wpi::print(stderr,
"JSpan was passed a null pointer at\n",
312 :
JSpanBase(env, jarr, jarr ? env->GetArrayLength(jarr) : 0) {}
315 if (m_jarr && m_elements) {
316 constexpr jint mode = std::is_const_v<T> ? JNI_ABORT : 0;
317 if constexpr (IsCritical) {
318 m_env->ReleasePrimitiveArrayCritical(m_jarr, m_elements, mode);
320 ArrHelper::ReleaseArrayElements(m_env, m_jarr, m_elements, mode);
325 operator std::span<T, Size>()
const {
return array(); }
331 if constexpr (Size == std::dynamic_extent) {
336 return std::span<T, Size>{m_elements, m_size};
339 T*
begin()
const {
return m_elements; }
341 T*
end()
const {
return m_elements + m_size; }
343 bool is_valid()
const {
return m_valid && m_elements !=
nullptr; }
345 explicit operator bool()
const {
return is_valid(); }
347 T*
data()
const {
return m_elements; }
349 size_t size()
const {
return m_size; }
351 const T&
operator[](
size_t i)
const {
return m_elements[i]; }
354 requires(!std::is_const_v<T>)
356 return m_elements[i];
361 operator std::string_view() const
362 requires
std::is_same_v<
std::remove_cv_t<T>, jbyte>
367 std::string_view
str() const
368 requires
std::is_same_v<
std::remove_cv_t<T>, jbyte>
374 return {
reinterpret_cast<const char*
>(arr.data()), arr.size()};
377 std::span<copy_cv_t<T, uint8_t>, Size>
uarray() const
378 requires
std::is_same_v<
std::remove_cv_t<T>, jbyte>
384 return {
reinterpret_cast<const uint8_t*
>(arr.data()), arr.size()};
389 template <
typename U>
390 requires(
sizeof(U) ==
sizeof(jlong) && std::integral<U> &&
392 operator std::span<U, Size>()
const
393 requires std::is_same_v<std::remove_cv_t<T>, jlong>
399 return {
reinterpret_cast<U*
>(arr.data()), arr.size()};
407 jarray_type m_jarr =
nullptr;
409 std::remove_cv_t<T>* m_elements;
415template <
typename T,
size_t Extent = std::dynamic_extent>
418template <
typename T,
size_t Extent = std::dynamic_extent>
434 return env->NewString(chars.
begin(), chars.
size());
442 static jintArray
ToJava(JNIEnv* env, std::span<const T> arr) {
443 if constexpr (
sizeof(T) ==
sizeof(jint) && std::integral<T>) {
445 jintArray jarr = env->NewIntArray(arr.size());
449 env->SetIntArrayRegion(jarr, 0, arr.size(),
450 reinterpret_cast<const jint*
>(arr.data()));
457 jintArray jarr = env->NewIntArray(arr.size());
462 static_cast<jint*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
466 for (
size_t i = 0; i < arr.size(); ++i) {
467 elements[i] =
static_cast<jint
>(arr[i]);
469 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
495inline jintArray
MakeJIntArray(JNIEnv* env, std::span<T> arr) {
534 jbyteArray jarr = env->NewByteArray(str.size());
538 env->SetByteArrayRegion(jarr, 0, str.size(),
539 reinterpret_cast<const jbyte*
>(str.data()));
550 jbooleanArray jarr = env->NewBooleanArray(arr.size());
555 static_cast<jboolean*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
559 for (
size_t i = 0; i < arr.size(); ++i) {
560 elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
562 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
573 jbooleanArray jarr = env->NewBooleanArray(arr.size());
578 static_cast<jboolean*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
582 for (
size_t i = 0; i < arr.size(); ++i) {
583 elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
585 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
591#define WPI_JNI_MAKEJARRAY(T, F) \
592 inline T##Array MakeJ##F##Array(JNIEnv* env, std::span<const T> arr) { \
593 T##Array jarr = env->New##F##Array(arr.size()); \
597 env->Set##F##ArrayRegion(jarr, 0, arr.size(), arr.data()); \
607#undef WPI_JNI_MAKEJARRAY
610 requires(
sizeof(
typename T::value_type) ==
sizeof(jlong) &&
611 std::integral<typename T::value_type>)
613 jlongArray jarr = env->NewLongArray(arr.size());
617 env->SetLongArrayRegion(jarr, 0, arr.size(),
618 reinterpret_cast<const jlong*
>(arr.data()));
629 std::span<const std::string> arr) {
630 static JClass stringCls{env,
"java/lang/String"};
634 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
638 for (
size_t i = 0; i < arr.size(); ++i) {
640 env->SetObjectArrayElement(jarr, i, elem.obj());
652 std::span<std::string_view> arr) {
653 static JClass stringCls{env,
"java/lang/String"};
657 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
661 for (
size_t i = 0; i < arr.size(); ++i) {
663 env->SetObjectArrayElement(jarr, i, elem.obj());
688 void Main()
override;
699 void SetFunc(JNIEnv* env, jobject func, jmethodID mid);
701 template <
typename... Args>
702 void Send(Args&&... args);
707 auto thr = this->GetThread();
713 env->DeleteGlobalRef(thr->m_func);
716 thr->m_func = env->NewGlobalRef(func);
721template <
typename... Args>
723 auto thr = this->GetThread();
727 thr->m_queue.emplace(std::forward<Args>(args)...);
728 thr->m_cond.notify_one();
734 JavaVMAttachArgs args;
735 args.version = JNI_VERSION_1_2;
736 args.name =
const_cast<char*
>(T::GetName());
737 args.group =
nullptr;
738 jint rs = T::GetJVM()->AttachCurrentThreadAsDaemon(
739 reinterpret_cast<void**
>(&env), &args);
744 std::unique_lock lock(m_mutex);
746 m_cond.wait(lock, [&] {
return !(m_active && m_queue.empty()); });
750 while (!m_queue.empty()) {
754 auto item = std::move(m_queue.front());
759 item.CallJava(env, func, mid);
760 if (env->ExceptionCheck()) {
761 env->ExceptionDescribe();
762 env->ExceptionClear();
768 JavaVM* jvm = T::GetJVM();
770 jvm->DetachCurrentThread();
785 static JClass throwableCls(env,
"java/lang/Throwable");
789 static jmethodID constructorId =
nullptr;
790 if (!constructorId) {
791 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
793 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
798 static jmethodID getStackTraceId =
nullptr;
799 if (!getStackTraceId) {
800 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
801 "()[Ljava/lang/StackTraceElement;");
806 env,
static_cast<jobjectArray
>(
807 env->CallObjectMethod(throwable, getStackTraceId)));
814 jsize stackTraceLength = env->GetArrayLength(stackTrace);
817 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
818 if (!stackTraceElementCls) {
821 static jmethodID toStringId =
nullptr;
823 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
824 "()Ljava/lang/String;");
827 bool foundFirst =
false;
830 for (jsize i = 0; i < stackTraceLength; i++) {
833 env, env->GetObjectArrayElement(stackTrace, i));
837 env,
static_cast<jstring
>(
838 env->CallObjectMethod(curStackTraceElement, toStringId)));
840 if (!stackElementString) {
852 oss <<
"\tat " << elem <<
'\n';
859 std::string_view excludeFuncPrefix) {
861 static JClass throwableCls(env,
"java/lang/Throwable");
865 static jmethodID constructorId =
nullptr;
866 if (!constructorId) {
867 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
869 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
874 static jmethodID getStackTraceId =
nullptr;
875 if (!getStackTraceId) {
876 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
877 "()[Ljava/lang/StackTraceElement;");
882 env,
static_cast<jobjectArray
>(
883 env->CallObjectMethod(throwable, getStackTraceId)));
890 jsize stackTraceLength = env->GetArrayLength(stackTrace);
893 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
894 if (!stackTraceElementCls) {
897 static jmethodID toStringId =
nullptr;
899 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
900 "()Ljava/lang/String;");
903 bool haveLoc =
false;
906 for (jsize i = 0; i < stackTraceLength; i++) {
909 env, env->GetObjectArrayElement(stackTrace, i));
913 env,
static_cast<jstring
>(
914 env->CallObjectMethod(curStackTraceElement, toStringId)));
916 if (!stackElementString) {
929 }
else if (i > 1 && !haveLoc && !excludeFuncPrefix.empty() &&
953 env->GetMethodID(
m_cls,
"<init>",
"(Ljava/lang/String;)V");
957 void Throw(JNIEnv* env, jstring msg) {
959 env->Throw(
static_cast<jthrowable
>(
exception));
962 void Throw(JNIEnv* env, std::string_view msg) {
966 explicit operator bool()
const {
return m_constructor; }
969 jmethodID m_constructor =
nullptr;
This file defines the SmallString class.
This file defines the SmallVector 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:302
Definition SafeThread.h:33
Definition SafeThread.h:124
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:27
std::string_view str() const
Explicit conversion to std::string_view.
Definition SmallString.h:186
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition SmallVector.h:1212
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition sha1.h:30
void pop_back()
Definition SmallVector.h:441
void push_back(const T &Elt)
Definition SmallVector.h:429
size_t size() const
Definition SmallVector.h:99
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition SmallVector.h:302
iterator begin()
Definition SmallVector.h:283
void SetJoinAtExit(bool joinAtExit)
Definition SafeThread.h:106
Definition jni_util.h:696
JCallbackManager()
Definition jni_util.h:698
void SetFunc(JNIEnv *env, jobject func, jmethodID mid)
Definition jni_util.h:706
void Send(Args &&... args)
Definition jni_util.h:722
Generic callback thread implementation.
Definition jni_util.h:686
jmethodID m_mid
Definition jni_util.h:692
jobject m_func
Definition jni_util.h:691
std::queue< T > m_queue
Definition jni_util.h:690
void Main() override
Definition jni_util.h:732
Finds a class and keeps it as a global reference.
Definition jni_util.h:52
JClass(JNIEnv *env, const char *name)
Definition jni_util.h:56
jclass m_cls
Definition jni_util.h:77
void free(JNIEnv *env)
Definition jni_util.h:65
Finds an exception class and keep it as a global reference.
Definition jni_util.h:947
void Throw(JNIEnv *env, std::string_view msg)
Definition jni_util.h:962
JException(JNIEnv *env, const char *name)
Definition jni_util.h:950
void Throw(JNIEnv *env, jstring msg)
Definition jni_util.h:957
JGlobal(JNIEnv *env, T obj)
Definition jni_util.h:90
void free(JNIEnv *env)
Definition jni_util.h:94
T m_cls
Definition jni_util.h:106
Container class for cleaning up Java local references.
Definition jni_util.h:115
JLocal & operator=(const JLocal &)=delete
~JLocal()
Definition jni_util.h:129
JLocal(JLocal &&oth)
Definition jni_util.h:119
JLocal & operator=(JLocal &&oth)
Definition jni_util.h:123
T obj()
Definition jni_util.h:135
JLocal(JNIEnv *env, T obj)
Definition jni_util.h:117
JLocal(const JLocal &)=delete
Definition jni_util.h:775
static JSingletonCallbackManager< T > & GetInstance()
Definition jni_util.h:777
Java string (jstring) reference.
Definition jni_util.h:152
std::string_view str() const
Definition jni_util.h:172
WPI_String wpi_str() const
Definition jni_util.h:175
const char * c_str() const
Definition jni_util.h:173
size_t size() const
Definition jni_util.h:174
JStringRef(JNIEnv *env, jstring str)
Definition jni_util.h:154
Helper class for working with JNI arrays.
Definition jni_util.h:248
JSpanBase(const JSpanBase &)=delete
T & operator[](size_t i)
Definition jni_util.h:353
JSpanBase(JNIEnv *env, jarray_type jarr)
Definition jni_util.h:311
bool is_valid() const
Definition jni_util.h:343
T * end() const
Definition jni_util.h:341
JSpanBase & operator=(JSpanBase &&other)
Definition jni_util.h:266
JSpanBase(JNIEnv *env, jarray_type jarr, size_t size)
Definition jni_util.h:292
std::span< copy_cv_t< T, uint8_t >, Size > uarray() const
Definition jni_util.h:377
T * begin() const
Definition jni_util.h:339
const T & operator[](size_t i) const
Definition jni_util.h:351
size_t size() const
Definition jni_util.h:349
T * data() const
Definition jni_util.h:347
JSpanBase(JNIEnv *env, jobject bb, size_t size)
Definition jni_util.h:278
std::string_view str() const
Definition jni_util.h:367
JSpanBase(JSpanBase &&other)
Definition jni_util.h:256
std::span< T, Size > array() const
Definition jni_util.h:327
JSpanBase & operator=(const JSpanBase &)=delete
~JSpanBase()
Definition jni_util.h:314
A raw_ostream that writes to an std::string.
Definition raw_ostream.h:589
std::string & str()
Returns the string's reference.
Definition raw_ostream.h:607
Definition jni_util.h:210
#define WPI_JNI_MAKEJARRAY(T, F)
Definition jni_util.h:591
#define WPI_JNI_ARRAYHELPER(T, F)
Definition jni_util.h:186
detail namespace with internal helper functions
Definition input_adapters.h:32
Implement std::hash so that hash_code can be used in STL containers.
Definition PointerIntPair.h:280
constexpr bool is_qualification_convertible_v
Definition jni_util.h:228
typename copy_cv< CvSrc, Dest >::type copy_cv_t
Definition jni_util.h:225
Java Native Interface (JNI) utility functions.
Definition jni_util.h:29
jlongArray MakeJLongArray(JNIEnv *env, const T &arr)
Definition jni_util.h:612
jintArray MakeJIntArray(JNIEnv *env, std::span< const T > arr)
Convert a span to a jintArray.
Definition jni_util.h:484
jstring MakeJString(JNIEnv *env, std::string_view str)
Convert a UTF8 string into a jstring.
Definition jni_util.h:431
std::string GetJavaStackTrace(JNIEnv *env, std::string *func=nullptr, std::string_view excludeFuncPrefix={})
Gets a Java stack trace.
Definition jni_util.h:858
jbooleanArray MakeJBooleanArray(JNIEnv *env, std::span< const int > arr)
Convert an array of integers into a jbooleanArray.
Definition jni_util.h:549
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:628
jbyteArray MakeJByteArray(JNIEnv *env, std::span< const uint8_t > str)
Convert a span into a jbyteArray.
Definition jni_util.h:533
bool convertUTF8ToUTF16String(std::string_view SrcUTF8, SmallVectorImpl< UTF16 > &DstUTF16)
Converts a UTF-8 string into a UTF-16 string with native endianness.
void print(wpi::raw_ostream &os, const S &format_str, Args &&... args)
Prints formatted data to the stream os.
Definition raw_ostream.h:25
constexpr WPI_String make_string(std::string_view view)
Converts a string_view to a WPI_String.
Definition string.h:33
bool Boolean
Definition ConvertUTF.h:130
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:235
A const UTF8 string.
Definition string.h:14
const char * name
Definition jni_util.h:81
JClass * cls
Definition jni_util.h:82
Definition jni_util.h:972
JException * cls
Definition jni_util.h:974
const char * name
Definition jni_util.h:973
Definition jni_util.h:184
Definition jni_util.h:441
static jintArray ToJava(JNIEnv *env, std::span< const T > arr)
Definition jni_util.h:442
Definition jni_util.h:214
U2 type
Definition jni_util.h:221