20#include "wpi/util/SmallVector.hpp"
21#include "wpi/util/StringExtras.hpp"
24#include "wpi/util/raw_ostream.hpp"
43 std::string_view excludeFuncPrefix = {});
56 jclass local = env->FindClass(
name);
60 m_cls =
static_cast<jclass
>(env->NewGlobalRef(local));
61 env->DeleteLocalRef(local);
66 env->DeleteGlobalRef(
m_cls);
71 explicit operator bool()
const {
return m_cls; }
73 operator jclass()
const {
return m_cls; }
90 m_cls =
static_cast<T
>(env->NewGlobalRef(obj));
95 env->DeleteGlobalRef(
m_cls);
100 explicit operator bool()
const {
return m_cls; }
102 operator T()
const {
return m_cls; }
130 m_env->DeleteLocalRef(m_obj);
133 operator T() {
return m_obj; }
155 jsize
size = env->GetStringLength(
str);
156 const jchar* chars = env->GetStringCritical(
str,
nullptr);
159 env->ReleaseStringCritical(
str, chars);
166 m_str.push_back(
'\0');
170 operator std::string_view()
const {
return m_str.str(); }
171 std::string_view
str()
const {
return m_str.str(); }
172 const char*
c_str()
const {
return m_str.data(); }
173 size_t size()
const {
return m_str.size(); }
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
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},
258 m_jarr{other.m_jarr},
259 m_size{other.m_size},
260 m_elements{other.m_elements} {
261 other.m_jarr =
nullptr;
262 other.m_elements =
nullptr;
266 m_valid = other.m_valid;
268 m_jarr = other.m_jarr;
269 m_size = other.m_size;
270 m_elements = other.m_elements;
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},
283 m_elements{static_cast<
std::remove_cv_t<T>*>(
284 bb ? env->GetDirectBufferAddress(bb) : nullptr)} {
292 : m_valid{Size ==
std::dynamic_extent ||
size == Size},
296 m_elements{nullptr} {
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);
311 :
JSpanBase(env, jarr, jarr ? env->GetArrayLength(jarr) : 0) {}
314 if (m_jarr && m_elements) {
315 constexpr jint mode = std::is_const_v<T> ? JNI_ABORT : 0;
316 if constexpr (IsCritical) {
317 m_env->ReleasePrimitiveArrayCritical(m_jarr, m_elements, mode);
319 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>
432 SmallVector<UTF16, 128> chars;
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);
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()); \
609#undef WPI_JNI_MAKEJARRAY
612 requires(
sizeof(
typename T::value_type) ==
sizeof(jlong) &&
613 std::integral<typename T::value_type>)
615 jlongArray jarr = env->NewLongArray(arr.size());
619 env->SetLongArrayRegion(jarr, 0, arr.size(),
620 reinterpret_cast<const jlong*
>(arr.data()));
631 std::span<const std::string> arr) {
632 static JClass stringCls{env,
"java/lang/String"};
636 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
640 for (
size_t i = 0; i < arr.size(); ++i) {
642 env->SetObjectArrayElement(jarr, i, elem.
obj());
654 std::span<std::string_view> arr) {
655 static JClass stringCls{env,
"java/lang/String"};
659 jobjectArray jarr = env->NewObjectArray(arr.size(), stringCls,
nullptr);
663 for (
size_t i = 0; i < arr.size(); ++i) {
665 env->SetObjectArrayElement(jarr, i, elem.
obj());
690 void Main()
override;
701 void SetFunc(JNIEnv* env, jobject func, jmethodID mid);
703 template <
typename... Args>
704 void Send(Args&&... args);
715 env->DeleteGlobalRef(thr->m_func);
718 thr->m_func = env->NewGlobalRef(func);
723template <
typename... Args>
729 thr->m_queue.emplace(std::forward<Args>(args)...);
730 thr->m_cond.notify_one();
736 JavaVMAttachArgs args;
737 args.version = JNI_VERSION_1_2;
738 args.name =
const_cast<char*
>(T::GetName());
739 args.group =
nullptr;
740 jint rs = T::GetJVM()->AttachCurrentThreadAsDaemon(
741 reinterpret_cast<void**
>(&env), &args);
746 std::unique_lock lock(
m_mutex);
756 auto item = std::move(
m_queue.front());
761 item.CallJava(env, func, mid);
762 if (env->ExceptionCheck()) {
763 env->ExceptionDescribe();
764 env->ExceptionClear();
770 JavaVM* jvm = T::GetJVM();
772 jvm->DetachCurrentThread();
787 static JClass throwableCls(env,
"java/lang/Throwable");
791 static jmethodID constructorId =
nullptr;
792 if (!constructorId) {
793 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
795 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
800 static jmethodID getStackTraceId =
nullptr;
801 if (!getStackTraceId) {
802 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
803 "()[Ljava/lang/StackTraceElement;");
808 env,
static_cast<jobjectArray
>(
809 env->CallObjectMethod(throwable, getStackTraceId)));
816 jsize stackTraceLength = env->GetArrayLength(stackTrace);
819 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
820 if (!stackTraceElementCls) {
823 static jmethodID toStringId =
nullptr;
825 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
826 "()Ljava/lang/String;");
829 bool foundFirst =
false;
831 raw_string_ostream oss(buf);
832 for (jsize i = 0; i < stackTraceLength; i++) {
835 env, env->GetObjectArrayElement(stackTrace, i));
839 env,
static_cast<jstring
>(
840 env->CallObjectMethod(curStackTraceElement, toStringId)));
842 if (!stackElementString) {
849 if (wpi::util::starts_with(elem, skipPrefix)) {
854 oss <<
"\tat " << elem <<
'\n';
861 std::string_view excludeFuncPrefix) {
863 static JClass throwableCls(env,
"java/lang/Throwable");
867 static jmethodID constructorId =
nullptr;
868 if (!constructorId) {
869 constructorId = env->GetMethodID(throwableCls,
"<init>",
"()V");
871 JLocal<jobject> throwable(env, env->NewObject(throwableCls, constructorId));
876 static jmethodID getStackTraceId =
nullptr;
877 if (!getStackTraceId) {
878 getStackTraceId = env->GetMethodID(throwableCls,
"getStackTrace",
879 "()[Ljava/lang/StackTraceElement;");
884 env,
static_cast<jobjectArray
>(
885 env->CallObjectMethod(throwable, getStackTraceId)));
892 jsize stackTraceLength = env->GetArrayLength(stackTrace);
895 static JClass stackTraceElementCls(env,
"java/lang/StackTraceElement");
896 if (!stackTraceElementCls) {
899 static jmethodID toStringId =
nullptr;
901 toStringId = env->GetMethodID(stackTraceElementCls,
"toString",
902 "()Ljava/lang/String;");
905 bool haveLoc =
false;
907 raw_string_ostream oss(buf);
908 for (jsize i = 0; i < stackTraceLength; i++) {
911 env, env->GetObjectArrayElement(stackTrace, i));
915 env,
static_cast<jstring
>(
916 env->CallObjectMethod(curStackTraceElement, toStringId)));
918 if (!stackElementString) {
931 }
else if (i > 1 && !haveLoc && !excludeFuncPrefix.empty() &&
932 !wpi::util::starts_with(elem, excludeFuncPrefix)) {
955 env->GetMethodID(
m_cls,
"<init>",
"(Ljava/lang/String;)V");
959 void Throw(JNIEnv* env, jstring msg) {
961 env->Throw(
static_cast<jthrowable
>(
exception));
964 void Throw(JNIEnv* env, std::string_view msg) {
968 explicit operator bool()
const {
return m_constructor; }
971 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:301
@ name
Definition base.h:690
wpi::util::mutex m_mutex
Definition SafeThread.hpp:27
std::atomic_bool m_active
Definition SafeThread.hpp:28
Definition SafeThread.hpp:32
wpi::util::condition_variable m_cond
Definition SafeThread.hpp:36
Definition SafeThread.hpp:123
Proxy GetThread() const
Definition SafeThread.hpp:132
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.hpp:27
Definition BooleanTopic.hpp:24
void SetJoinAtExit(bool joinAtExit)
Definition SafeThread.hpp:105
void Send(Args &&... args)
Definition jni_util.hpp:724
void SetFunc(JNIEnv *env, jobject func, jmethodID mid)
Definition jni_util.hpp:708
JCallbackManager()
Definition jni_util.hpp:700
Generic callback thread implementation.
Definition jni_util.hpp:688
void Main() override
Definition jni_util.hpp:734
std::queue< T > m_queue
Definition jni_util.hpp:692
jmethodID m_mid
Definition jni_util.hpp:694
jobject m_func
Definition jni_util.hpp:693
Finds a class and keeps it as a global reference.
Definition jni_util.hpp:51
void free(JNIEnv *env)
Definition jni_util.hpp:64
jclass m_cls
Definition jni_util.hpp:76
JClass(JNIEnv *env, const char *name)
Definition jni_util.hpp:55
Finds an exception class and keep it as a global reference.
Definition jni_util.hpp:949
JException(JNIEnv *env, const char *name)
Definition jni_util.hpp:952
void Throw(JNIEnv *env, std::string_view msg)
Definition jni_util.hpp:964
void Throw(JNIEnv *env, jstring msg)
Definition jni_util.hpp:959
T m_cls
Definition jni_util.hpp:105
JGlobal(JNIEnv *env, T obj)
Definition jni_util.hpp:89
void free(JNIEnv *env)
Definition jni_util.hpp:93
Container class for cleaning up Java local references.
Definition jni_util.hpp:114
JLocal & operator=(const JLocal &)=delete
JLocal(JNIEnv *env, T obj)
Definition jni_util.hpp:116
~JLocal()
Definition jni_util.hpp:128
JLocal(JLocal &&oth)
Definition jni_util.hpp:118
JLocal(const JLocal &)=delete
T obj()
Definition jni_util.hpp:134
JLocal & operator=(JLocal &&oth)
Definition jni_util.hpp:122
Definition jni_util.hpp:777
static JSingletonCallbackManager< T > & GetInstance()
Definition jni_util.hpp:779
Java string (jstring) reference.
Definition jni_util.hpp:151
JStringRef(JNIEnv *env, jstring str)
Definition jni_util.hpp:153
std::string_view str() const
Definition jni_util.hpp:171
WPI_String wpi_str() const
Definition jni_util.hpp:174
size_t size() const
Definition jni_util.hpp:173
const char * c_str() const
Definition jni_util.hpp:172
Helper class for working with JNI arrays.
Definition jni_util.hpp:247
JSpanBase & operator=(JSpanBase &&other)
Definition jni_util.hpp:265
const T & operator[](size_t i) const
Definition jni_util.hpp:351
JSpanBase(const JSpanBase &)=delete
T * data() const
Definition jni_util.hpp:347
std::span< T, Size > array() const
Definition jni_util.hpp:327
std::string_view str() const
Definition jni_util.hpp:367
T * end() const
Definition jni_util.hpp:341
JSpanBase(JNIEnv *env, jobject bb, size_t size)
Definition jni_util.hpp:277
std::span< copy_cv_t< T, uint8_t >, Size > uarray() const
Definition jni_util.hpp:377
~JSpanBase()
Definition jni_util.hpp:313
bool is_valid() const
Definition jni_util.hpp:343
JSpanBase(JSpanBase &&other)
Definition jni_util.hpp:255
T & operator[](size_t i)
Definition jni_util.hpp:353
JSpanBase(JNIEnv *env, jarray_type jarr)
Definition jni_util.hpp:310
T * begin() const
Definition jni_util.hpp:339
JSpanBase & operator=(const JSpanBase &)=delete
JSpanBase(JNIEnv *env, jarray_type jarr, size_t size)
Definition jni_util.hpp:291
size_t size() const
Definition jni_util.hpp:349
Definition jni_util.hpp:209
#define WPI_JNI_MAKEJARRAY(T, F)
Definition jni_util.hpp:591
#define WPI_JNI_ARRAYHELPER(T, F)
Definition jni_util.hpp:185
Converts a string literal into a format string that will be parsed at compile time and converted into...
Definition printf.h:50
Definition StringMap.hpp:773
constexpr bool is_qualification_convertible_v
Definition jni_util.hpp:227
typename copy_cv< CvSrc, Dest >::type copy_cv_t
Definition jni_util.hpp:224
Java Native Interface (JNI) utility functions.
Definition jni_util.hpp:28
jbyteArray MakeJByteArray(JNIEnv *env, std::span< const uint8_t > str)
Convert a span into a jbyteArray.
Definition jni_util.hpp:533
jstring MakeJString(JNIEnv *env, std::string_view str)
Convert a UTF8 string into a jstring.
Definition jni_util.hpp:431
jintArray MakeJIntArray(JNIEnv *env, std::span< const T > arr)
Convert a span to a jintArray.
Definition jni_util.hpp:484
jbooleanArray MakeJBooleanArray(JNIEnv *env, std::span< const int > arr)
Convert an array of integers into a jbooleanArray.
Definition jni_util.hpp:549
jlongArray MakeJLongArray(JNIEnv *env, const T &arr)
Definition jni_util.hpp:614
std::string GetJavaStackTrace(JNIEnv *env, std::string *func=nullptr, std::string_view excludeFuncPrefix={})
Gets a Java stack trace.
Definition jni_util.hpp:860
jobjectArray MakeJStringArray(JNIEnv *env, std::span< const std::string > arr)
Convert an array of std::string into a jarray of jstring.
Definition jni_util.hpp:630
detail::JSpanBase< T, false, Extent > JSpan
Definition jni_util.hpp:416
detail::JSpanBase< T, true, Extent > CriticalJSpan
Definition jni_util.hpp:419
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.
bool Boolean
Definition ConvertUTF.hpp:130
constexpr WPI_String make_string(std::string_view view)
Converts a string_view to a WPI_String.
Definition string.hpp:24
void print(wpi::util::raw_ostream &os, const S &format_str, Args &&... args)
Prints formatted data to the stream os.
Definition raw_ostream.hpp:24
A const UTF8 string.
Definition string.h:12
Definition jni_util.hpp:79
JClass * cls
Definition jni_util.hpp:81
const char * name
Definition jni_util.hpp:80
Definition jni_util.hpp:974
JException * cls
Definition jni_util.hpp:976
const char * name
Definition jni_util.hpp:975
Definition jni_util.hpp:183
Definition jni_util.hpp:441
static jintArray ToJava(JNIEnv *env, std::span< const T > arr)
Definition jni_util.hpp:442
Definition jni_util.hpp:213
U2 type
Definition jni_util.hpp:220