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 wpi::print(stderr,
"JStringRef was passed a null pointer at\n",
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},
262 other.m_jarr =
nullptr;
263 other.m_elements =
nullptr;
267 m_valid = other.m_valid;
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},
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},
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) {}
316 constexpr jint mode = std::is_const_v<T> ? JNI_ABORT : 0;
317 if constexpr (IsCritical) {
325 operator std::span<T, Size>()
const {
return array(); }
331 if constexpr (Size == std::dynamic_extent) {
345 explicit operator bool()
const {
return is_valid(); }
354 requires(!std::is_const_v<T>)
362 requires
std::is_same_v<
std::remove_cv_t<T>, jbyte>
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> &&
391 is_qualification_convertible_v<T, 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()};
412template <
typename T,
size_t Extent = std::dynamic_extent>
415template <
typename T,
size_t Extent = std::dynamic_extent>
431 return env->NewString(chars.
begin(), chars.
size());
439 static jintArray
ToJava(JNIEnv* env, std::span<const T> arr) {
440 if constexpr (
sizeof(T) ==
sizeof(jint) && std::integral<T>) {
442 jintArray jarr = env->NewIntArray(arr.size());
446 env->SetIntArrayRegion(jarr, 0, arr.size(),
447 reinterpret_cast<const jint*
>(arr.data()));
454 jintArray jarr = env->NewIntArray(arr.size());
459 static_cast<jint*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
463 for (
size_t i = 0; i < arr.size(); ++i) {
464 elements[i] =
static_cast<jint
>(arr[i]);
466 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
492inline jintArray
MakeJIntArray(JNIEnv* env, std::span<T> arr) {
531 jbyteArray jarr = env->NewByteArray(str.size());
535 env->SetByteArrayRegion(jarr, 0, str.size(),
536 reinterpret_cast<const jbyte*
>(str.data()));
547 jbooleanArray jarr = env->NewBooleanArray(arr.size());
552 static_cast<jboolean*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
556 for (
size_t i = 0; i < arr.size(); ++i) {
557 elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
559 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
570 jbooleanArray jarr = env->NewBooleanArray(arr.size());
575 static_cast<jboolean*
>(env->GetPrimitiveArrayCritical(jarr,
nullptr));
579 for (
size_t i = 0; i < arr.size(); ++i) {
580 elements[i] = arr[i] ? JNI_TRUE : JNI_FALSE;
582 env->ReleasePrimitiveArrayCritical(jarr, elements, 0);
588#define WPI_JNI_MAKEJARRAY(T, F) \
589 inline T##Array MakeJ##F##Array(JNIEnv* env, std::span<const T> arr) { \
590 T##Array jarr = env->New##F##Array(arr.size()); \
594 env->Set##F##ArrayRegion(jarr, 0, arr.size(), arr.data()); \
604#undef WPI_JNI_MAKEJARRAY
607 requires(
sizeof(
typename T::value_type) ==
sizeof(jlong) &&
608 std::integral<typename T::value_type>)
610 jlongArray jarr = env->NewLongArray(arr.size());
614 env->SetLongArrayRegion(jarr, 0, arr.size(),
615 reinterpret_cast<const jlong*
>(arr.data()));
626 std::span<const std::string> arr) {
627 static JClass stringCls{env,
"java/lang/String"};
631 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
635 for (
size_t i = 0; i < arr.size(); ++i) {
637 env->SetObjectArrayElement(jarr, i, elem.obj());
649 std::span<std::string_view> arr) {
650 static JClass stringCls{env,
"java/lang/String"};
654 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
658 for (
size_t i = 0; i < arr.size(); ++i) {
660 env->SetObjectArrayElement(jarr, i, elem.obj());
685 void Main()
override;
696 void SetFunc(JNIEnv* env, jobject func, jmethodID mid);
698 template <
typename... Args>
699 void Send(Args&&... args);
704 auto thr = this->GetThread();
710 env->DeleteGlobalRef(thr->m_func);
713 thr->m_func = env->NewGlobalRef(func);
718template <
typename... Args>
720 auto thr = this->GetThread();
724 thr->m_queue.emplace(std::forward<Args>(args)...);
725 thr->m_cond.notify_one();
731 JavaVMAttachArgs args;
732 args.version = JNI_VERSION_1_2;
733 args.name =
const_cast<char*
>(T::GetName());
734 args.group =
nullptr;
735 jint rs = T::GetJVM()->AttachCurrentThreadAsDaemon(
736 reinterpret_cast<void**
>(&env), &args);
741 std::unique_lock lock(m_mutex);
743 m_cond.wait(lock, [&] {
return !(m_active && m_queue.empty()); });
747 while (!m_queue.empty()) {
751 auto item = std::move(m_queue.front());
756 item.CallJava(env, func, mid);
757 if (env->ExceptionCheck()) {
758 env->ExceptionDescribe();
759 env->ExceptionClear();
765 JavaVM* jvm = T::GetJVM();
767 jvm->DetachCurrentThread();
782 static JClass throwableCls(env,
"java/lang/Throwable");
786 static jmethodID constructorId =
nullptr;
787 if (!constructorId) {
788 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
790 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
795 static jmethodID getStackTraceId =
nullptr;
796 if (!getStackTraceId) {
797 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
798 "()[Ljava/lang/StackTraceElement;");
803 env,
static_cast<jobjectArray
>(
804 env->CallObjectMethod(throwable, getStackTraceId)));
811 jsize stackTraceLength = env->GetArrayLength(stackTrace);
814 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
815 if (!stackTraceElementCls) {
818 static jmethodID toStringId =
nullptr;
820 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
821 "()Ljava/lang/String;");
824 bool foundFirst =
false;
827 for (jsize i = 0; i < stackTraceLength; i++) {
830 env, env->GetObjectArrayElement(stackTrace, i));
834 env,
static_cast<jstring
>(
835 env->CallObjectMethod(curStackTraceElement, toStringId)));
837 if (!stackElementString) {
849 oss <<
"\tat " << elem <<
'\n';
858 static JClass throwableCls(env,
"java/lang/Throwable");
862 static jmethodID constructorId =
nullptr;
863 if (!constructorId) {
864 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
866 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
871 static jmethodID getStackTraceId =
nullptr;
872 if (!getStackTraceId) {
873 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
874 "()[Ljava/lang/StackTraceElement;");
879 env,
static_cast<jobjectArray
>(
880 env->CallObjectMethod(throwable, getStackTraceId)));
887 jsize stackTraceLength = env->GetArrayLength(stackTrace);
890 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
891 if (!stackTraceElementCls) {
894 static jmethodID toStringId =
nullptr;
896 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
897 "()Ljava/lang/String;");
900 bool haveLoc =
false;
903 for (jsize i = 0; i < stackTraceLength; i++) {
906 env, env->GetObjectArrayElement(stackTrace, i));
910 env,
static_cast<jstring
>(
911 env->CallObjectMethod(curStackTraceElement, toStringId)));
913 if (!stackElementString) {
926 }
else if (i > 1 && !haveLoc && !excludeFuncPrefix.empty() &&
950 env->GetMethodID(
m_cls,
"<init>",
"(Ljava/lang/String;)V");
954 void Throw(JNIEnv* env, jstring msg) {
956 env->Throw(
static_cast<jthrowable
>(
exception));
963 explicit operator bool()
const {
return m_constructor; }
966 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:290
Definition: SafeThread.h:33
Definition: SafeThread.h:124
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:1211
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:588
void pop_back()
Definition: SmallVector.h:440
void push_back(const T &Elt)
Definition: SmallVector.h:428
size_t size() const
Definition: SmallVector.h:98
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:301
iterator begin()
Definition: SmallVector.h:282
void SetJoinAtExit(bool joinAtExit)
Definition: SafeThread.h:106
Definition: jni_util.h:693
JCallbackManager()
Definition: jni_util.h:695
void SetFunc(JNIEnv *env, jobject func, jmethodID mid)
Definition: jni_util.h:703
void Send(Args &&... args)
Definition: jni_util.h:719
Generic callback thread implementation.
Definition: jni_util.h:683
jmethodID m_mid
Definition: jni_util.h:689
jobject m_func
Definition: jni_util.h:688
std::queue< T > m_queue
Definition: jni_util.h:687
void Main() override
Definition: jni_util.h:729
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:944
void Throw(JNIEnv *env, std::string_view msg)
Definition: jni_util.h:959
JException(JNIEnv *env, const char *name)
Definition: jni_util.h:947
void Throw(JNIEnv *env, jstring msg)
Definition: jni_util.h:954
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:772
static JSingletonCallbackManager< T > & GetInstance()
Definition: jni_util.h:774
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
size_t m_size
Definition: jni_util.h:406
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
std::remove_cv_t< T > * m_elements
Definition: jni_util.h:407
operator std::span< U, Size >() const std JNIEnv * m_env
Definition: jni_util.h:392
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
jarray_type m_jarr
Definition: jni_util.h:405
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:572
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:590
Definition: jni_util.h:210
#define WPI_JNI_MAKEJARRAY(T, F)
Definition: jni_util.h:588
#define WPI_JNI_ARRAYHELPER(T, F)
Definition: jni_util.h:186
detail namespace with internal helper functions
Definition: chrono.h:321
Implement std::hash so that hash_code can be used in STL containers.
Definition: array.h:89
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:609
jintArray MakeJIntArray(JNIEnv *env, std::span< const T > arr)
Convert a span to a jintArray.
Definition: jni_util.h:481
jstring MakeJString(JNIEnv *env, std::string_view str)
Convert a UTF8 string into a jstring.
Definition: jni_util.h:428
std::string GetJavaStackTrace(JNIEnv *env, std::string *func=nullptr, std::string_view excludeFuncPrefix={})
Gets a Java stack trace.
Definition: jni_util.h:855
jbooleanArray MakeJBooleanArray(JNIEnv *env, std::span< const int > arr)
Convert an array of integers into a jbooleanArray.
Definition: jni_util.h:546
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:625
jbyteArray MakeJByteArray(JNIEnv *env, std::span< const uint8_t > str)
Convert a span into a jbyteArray.
Definition: jni_util.h:530
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 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
Definition: jni_util.h:80
const char * name
Definition: jni_util.h:81
JClass * cls
Definition: jni_util.h:82
Definition: jni_util.h:969
JException * cls
Definition: jni_util.h:971
const char * name
Definition: jni_util.h:970
Definition: jni_util.h:184
Definition: jni_util.h:438
static jintArray ToJava(JNIEnv *env, std::span< const T > arr)
Definition: jni_util.h:439
Definition: jni_util.h:214
U2 type
Definition: jni_util.h:221
bool Boolean
Definition: ConvertUTF.h:130
basic_string_view< char > string_view
Definition: base.h:601