5#ifndef WPIUTIL_WPI_JNI_UTIL_H_
6#define WPIUTIL_WPI_JNI_UTIL_H_
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 fmt::print(stderr,
"JStringRef was passed a null pointer at\n",
185#define WPI_JNI_ARRAYHELPER(T, F) \
187 struct ArrayHelper<T> { \
188 using jarray_type = T##Array; \
189 static T* GetArrayElements(JNIEnv* env, jarray_type jarr) { \
190 return env->Get##F##ArrayElements(jarr, nullptr); \
192 static void ReleaseArrayElements(JNIEnv* env, jarray_type jarr, T* elems, \
194 env->Release##F##ArrayElements(jarr, elems, mode); \
206#undef WPI_JNI_ARRAYHELPER
210 requires {
typename ArrayHelper<std::remove_cv_t<T>>::jarray_type; };
212template <
typename CvSrc,
typename Dest>
215 using U0 = std::remove_cv_t<Dest>;
216 using U1 = std::conditional_t<std::is_const_v<CvSrc>,
const U0, U0>;
217 using U2 = std::conditional_t<std::is_volatile_v<CvSrc>,
volatile U1, U1>;
223template <
typename CvSrc,
typename Dest>
226template <
typename From,
typename To>
228 !(std::is_const_v<From> && !std::is_const_v<To>)&&!(
229 std::is_volatile_v<From> && !std::is_volatile_v<To>);
246template <JArrayType T,
bool IsCritical,
size_t Size = std::dynamic_extent>
249 using jarray_type =
typename ArrHelper::jarray_type;
256 : m_valid{other.m_valid},
261 other.m_jarr =
nullptr;
262 other.m_elements =
nullptr;
266 m_valid = other.m_valid;
271 other.m_valid =
false;
272 other.m_jarr =
nullptr;
273 other.m_elements =
nullptr;
278 requires(!IsCritical)
279 : m_valid{Size == std::dynamic_extent ||
size == Size},
284 bb ? env->GetDirectBufferAddress(bb) :
nullptr)} {
286 fmt::print(stderr,
"JSpan was passed a null pointer at\n",
292 : m_valid{Size ==
std::dynamic_extent ||
size == Size},
298 if constexpr (IsCritical) {
299 m_elements =
static_cast<std::remove_cv_t<T>*
>(
300 env->GetPrimitiveArrayCritical(jarr,
nullptr));
302 m_elements = ArrHelper::GetArrayElements(env, jarr);
305 fmt::print(stderr,
"JSpan was passed a null pointer at\n",
311 :
JSpanBase(env, jarr, jarr ? env->GetArrayLength(jarr) : 0) {}
315 constexpr jint mode = std::is_const_v<T> ? JNI_ABORT : 0;
316 if constexpr (IsCritical) {
324 operator std::span<T, Size>()
const {
return array(); }
330 if constexpr (Size == std::dynamic_extent) {
344 explicit operator bool()
const {
return is_valid(); }
353 requires(!std::is_const_v<T>)
361 requires
std::is_same_v<
std::remove_cv_t<T>, jbyte>
367 requires
std::is_same_v<
std::remove_cv_t<T>, jbyte>
373 return {
reinterpret_cast<const char*
>(arr.data()), arr.size()};
376 std::span<copy_cv_t<T, uint8_t>, Size>
uarray() const
377 requires
std::is_same_v<
std::remove_cv_t<T>, jbyte>
383 return {
reinterpret_cast<const uint8_t*
>(arr.data()), arr.size()};
388 template <
typename U>
389 requires(
sizeof(U) ==
sizeof(jlong) && std::integral<U> &&
390 is_qualification_convertible_v<T, U>)
391 operator std::span<U, Size>()
const
392 requires std::is_same_v<std::remove_cv_t<T>, jlong>
398 return {
reinterpret_cast<U*
>(arr.data()), arr.size()};
411template <
typename T,
size_t Extent = std::dynamic_extent>
414template <
typename T,
size_t Extent = std::dynamic_extent>
430 return env->NewString(chars.
begin(), chars.
size());
438 static jintArray
ToJava(JNIEnv* env, std::span<const T> arr) {
439 if constexpr (
sizeof(T) ==
sizeof(jint) && std::integral<T>) {
441 jintArray jarr = env->NewIntArray(arr.size());
445 env->SetIntArrayRegion(jarr, 0, arr.size(),
446 reinterpret_cast<const jint*
>(arr.data()));
453 jintArray jarr = env->NewIntArray(arr.size());
458 static_cast<jint*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
462 for (
size_t i = 0; i < arr.size(); ++i) {
463 elements[i] =
static_cast<jint
>(arr[i]);
465 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
491inline jintArray
MakeJIntArray(JNIEnv* env, std::span<T> arr) {
530 jbyteArray jarr = env->NewByteArray(str.size());
534 env->SetByteArrayRegion(jarr, 0, str.size(),
535 reinterpret_cast<const jbyte*
>(str.data()));
546 jbooleanArray jarr = env->NewBooleanArray(arr.size());
551 static_cast<jboolean*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
555 for (
size_t i = 0; i < arr.size(); ++i) {
556 elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
558 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
569 jbooleanArray jarr = env->NewBooleanArray(arr.size());
574 static_cast<jboolean*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
578 for (
size_t i = 0; i < arr.size(); ++i) {
579 elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
581 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
587#define WPI_JNI_MAKEJARRAY(T, F) \
588 inline T##Array MakeJ##F##Array(JNIEnv* env, std::span<const T> arr) { \
589 T##Array jarr = env->New##F##Array(arr.size()); \
593 env->Set##F##ArrayRegion(jarr, 0, arr.size(), arr.data()); \
603#undef WPI_JNI_MAKEJARRAY
606 requires(
sizeof(
typename T::value_type) ==
sizeof(jlong) &&
607 std::integral<typename T::value_type>)
609 jlongArray jarr = env->NewLongArray(arr.size());
613 env->SetLongArrayRegion(jarr, 0, arr.size(),
614 reinterpret_cast<const jlong*
>(arr.data()));
625 std::span<const std::string> arr) {
626 static JClass stringCls{env,
"java/lang/String"};
630 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
634 for (
size_t i = 0; i < arr.size(); ++i) {
636 env->SetObjectArrayElement(jarr, i, elem.obj());
648 std::span<std::string_view> arr) {
649 static JClass stringCls{env,
"java/lang/String"};
653 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
657 for (
size_t i = 0; i < arr.size(); ++i) {
659 env->SetObjectArrayElement(jarr, i, elem.obj());
684 void Main()
override;
695 void SetFunc(JNIEnv* env, jobject func, jmethodID mid);
697 template <
typename... Args>
698 void Send(Args&&... args);
703 auto thr = this->GetThread();
709 env->DeleteGlobalRef(thr->m_func);
712 thr->m_func = env->NewGlobalRef(func);
717template <
typename... Args>
719 auto thr = this->GetThread();
723 thr->m_queue.emplace(std::forward<Args>(args)...);
724 thr->m_cond.notify_one();
730 JavaVMAttachArgs args;
731 args.version = JNI_VERSION_1_2;
732 args.name =
const_cast<char*
>(T::GetName());
733 args.group =
nullptr;
734 jint rs = T::GetJVM()->AttachCurrentThreadAsDaemon(
735 reinterpret_cast<void**
>(&env), &args);
740 std::unique_lock lock(m_mutex);
742 m_cond.wait(lock, [&] {
return !(m_active && m_queue.empty()); });
746 while (!m_queue.empty()) {
750 auto item = std::move(m_queue.front());
755 item.CallJava(env, func, mid);
756 if (env->ExceptionCheck()) {
757 env->ExceptionDescribe();
758 env->ExceptionClear();
764 JavaVM* jvm = T::GetJVM();
766 jvm->DetachCurrentThread();
781 static JClass throwableCls(env,
"java/lang/Throwable");
785 static jmethodID constructorId =
nullptr;
786 if (!constructorId) {
787 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
789 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
794 static jmethodID getStackTraceId =
nullptr;
795 if (!getStackTraceId) {
796 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
797 "()[Ljava/lang/StackTraceElement;");
802 env,
static_cast<jobjectArray
>(
803 env->CallObjectMethod(throwable, getStackTraceId)));
810 jsize stackTraceLength = env->GetArrayLength(stackTrace);
813 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
814 if (!stackTraceElementCls) {
817 static jmethodID toStringId =
nullptr;
819 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
820 "()Ljava/lang/String;");
823 bool foundFirst =
false;
826 for (jsize i = 0; i < stackTraceLength; i++) {
829 env, env->GetObjectArrayElement(stackTrace, i));
833 env,
static_cast<jstring
>(
834 env->CallObjectMethod(curStackTraceElement, toStringId)));
836 if (!stackElementString) {
848 oss <<
"\tat " << elem <<
'\n';
857 static JClass throwableCls(env,
"java/lang/Throwable");
861 static jmethodID constructorId =
nullptr;
862 if (!constructorId) {
863 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
865 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
870 static jmethodID getStackTraceId =
nullptr;
871 if (!getStackTraceId) {
872 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
873 "()[Ljava/lang/StackTraceElement;");
878 env,
static_cast<jobjectArray
>(
879 env->CallObjectMethod(throwable, getStackTraceId)));
886 jsize stackTraceLength = env->GetArrayLength(stackTrace);
889 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
890 if (!stackTraceElementCls) {
893 static jmethodID toStringId =
nullptr;
895 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
896 "()Ljava/lang/String;");
899 bool haveLoc =
false;
902 for (jsize i = 0; i < stackTraceLength; i++) {
905 env, env->GetObjectArrayElement(stackTrace, i));
909 env,
static_cast<jstring
>(
910 env->CallObjectMethod(curStackTraceElement, toStringId)));
912 if (!stackElementString) {
925 }
else if (i > 1 && !haveLoc && !excludeFuncPrefix.empty() &&
949 env->GetMethodID(
m_cls,
"<init>",
"(Ljava/lang/String;)V");
953 void Throw(JNIEnv* env, jstring msg) {
955 env->Throw(
static_cast<jthrowable
>(
exception));
962 explicit operator bool()
const {
return m_constructor; }
965 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:289
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:1202
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:579
void pop_back()
Definition: SmallVector.h:430
void push_back(const T &Elt)
Definition: SmallVector.h:418
size_t size() const
Definition: SmallVector.h:98
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:291
iterator begin()
Definition: SmallVector.h:272
void SetJoinAtExit(bool joinAtExit)
Definition: SafeThread.h:106
Definition: jni_util.h:692
JCallbackManager()
Definition: jni_util.h:694
void SetFunc(JNIEnv *env, jobject func, jmethodID mid)
Definition: jni_util.h:702
void Send(Args &&... args)
Definition: jni_util.h:718
Generic callback thread implementation.
Definition: jni_util.h:682
jmethodID m_mid
Definition: jni_util.h:688
jobject m_func
Definition: jni_util.h:687
std::queue< T > m_queue
Definition: jni_util.h:686
void Main() override
Definition: jni_util.h:728
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:943
void Throw(JNIEnv *env, std::string_view msg)
Definition: jni_util.h:958
JException(JNIEnv *env, const char *name)
Definition: jni_util.h:946
void Throw(JNIEnv *env, jstring msg)
Definition: jni_util.h:953
Definition: jni_util.h:86
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:771
static JSingletonCallbackManager< T > & GetInstance()
Definition: jni_util.h:773
Java string (jstring) reference.
Definition: jni_util.h:152
std::string_view str() const
Definition: jni_util.h:172
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:247
size_t m_size
Definition: jni_util.h:405
JSpanBase(const JSpanBase &)=delete
T & operator[](size_t i)
Definition: jni_util.h:352
JSpanBase(JNIEnv *env, jarray_type jarr)
Definition: jni_util.h:310
bool is_valid() const
Definition: jni_util.h:342
T * end() const
Definition: jni_util.h:340
JSpanBase & operator=(JSpanBase &&other)
Definition: jni_util.h:265
JSpanBase(JNIEnv *env, jarray_type jarr, size_t size)
Definition: jni_util.h:291
std::span< copy_cv_t< T, uint8_t >, Size > uarray() const
Definition: jni_util.h:376
std::remove_cv_t< T > * m_elements
Definition: jni_util.h:406
operator std::span< U, Size >() const std JNIEnv * m_env
Definition: jni_util.h:391
T * begin() const
Definition: jni_util.h:338
const T & operator[](size_t i) const
Definition: jni_util.h:350
size_t size() const
Definition: jni_util.h:348
T * data() const
Definition: jni_util.h:346
jarray_type m_jarr
Definition: jni_util.h:404
JSpanBase(JNIEnv *env, jobject bb, size_t size)
Definition: jni_util.h:277
std::string_view str() const
Definition: jni_util.h:366
JSpanBase(JSpanBase &&other)
Definition: jni_util.h:255
std::span< T, Size > array() const
Definition: jni_util.h:326
JSpanBase & operator=(const JSpanBase &)=delete
~JSpanBase()
Definition: jni_util.h:313
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:572
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:590
Definition: jni_util.h:209
basic_string_view< char > string_view
Definition: core.h:501
void print(wpi::raw_ostream &os, const S &format_str, Args &&... args)
Prints formatted data to the stream os.
Definition: raw_ostream.h:25
#define WPI_JNI_MAKEJARRAY(T, F)
Definition: jni_util.h:587
#define WPI_JNI_ARRAYHELPER(T, F)
Definition: jni_util.h:185
detail namespace with internal helper functions
Definition: xchar.h:20
constexpr bool is_qualification_convertible_v
Definition: jni_util.h:227
typename copy_cv< CvSrc, Dest >::type copy_cv_t
Definition: jni_util.h:224
Java Native Interface (JNI) utility functions.
Definition: jni_util.h:29
jlongArray MakeJLongArray(JNIEnv *env, const T &arr)
Definition: jni_util.h:608
jintArray MakeJIntArray(JNIEnv *env, std::span< const T > arr)
Convert a span to a jintArray.
Definition: jni_util.h:480
jstring MakeJString(JNIEnv *env, std::string_view str)
Convert a UTF8 string into a jstring.
Definition: jni_util.h:427
std::string GetJavaStackTrace(JNIEnv *env, std::string *func=nullptr, std::string_view excludeFuncPrefix={})
Gets a Java stack trace.
Definition: jni_util.h:854
jbooleanArray MakeJBooleanArray(JNIEnv *env, std::span< const int > arr)
Convert an array of integers into a jbooleanArray.
Definition: jni_util.h:545
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:624
jbyteArray MakeJByteArray(JNIEnv *env, std::span< const uint8_t > str)
Convert a span into a jbyteArray.
Definition: jni_util.h:529
bool convertUTF8ToUTF16String(std::string_view SrcUTF8, SmallVectorImpl< UTF16 > &DstUTF16)
Converts a UTF-8 string into a UTF-16 string with native endianness.
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
Definition: jni_util.h:80
const char * name
Definition: jni_util.h:81
JClass * cls
Definition: jni_util.h:82
Definition: jni_util.h:968
JException * cls
Definition: jni_util.h:970
const char * name
Definition: jni_util.h:969
Definition: jni_util.h:183
Definition: jni_util.h:437
static jintArray ToJava(JNIEnv *env, std::span< const T > arr)
Definition: jni_util.h:438
Definition: jni_util.h:213
U2 type
Definition: jni_util.h:220
bool Boolean
Definition: ConvertUTF.h:130