UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
AndroidJavaEnv.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#if defined(USE_ANDROID_JNI) && USE_ANDROID_JNI
6
7#include "CoreTypes.h"
8#include "Containers/Array.h"
14#include <algorithm>
15#include <type_traits>
16#include <jni.h>
17
18namespace AndroidJavaEnv
19{
20 // Returns the java environment
21 UE_DEPRECATED(5.7, "Use InitializeJavaEnv() instead.")
26 //UE_DEPRECATED(5.7, "Use UE::Jni::Env global instead.")
28 CORE_API jclass FindJavaClass(const char* name);
29 CORE_API jclass FindJavaClassGlobalRef(const char* name);
30 UE_DEPRECATED(5.7, "Don't call this.")
33}
34
35#define UE_JNI_MEMBER(Member) \
36 ::UE::Jni::FMember{Member, #Member}
37
38#define UE_JNI_NATIVE_METHOD(Method) \
39 ::UE::Jni::FNativeMethod{#Method, ::UE::Jni::Signature<decltype(Method)>.GetData(), (void*)Method}
40
41template <typename T> requires std::is_pointer_v<T>
43
44namespace UE::Jni
45{
46 template <typename T>
47 struct TTraits
48 {
49 };
50
51 template <typename T>
52 struct TSignature
53 {
54 static constexpr FAnsiStringView Value = TTraits<T>::Signature;
55 };
56
57 template <typename T>
58 inline constexpr FAnsiStringView Signature = TSignature<T>::Value;
59
60 template <typename TRet, typename... TArgs>
61 struct TSignature<TRet (TArgs...)>
62 {
63 private:
64 static constexpr auto _Value = []
65 {
66 TStaticArray<char, (3 + ... + Signature<TArgs>.Len()) + Signature<TRet>.Len()> Value;
67 auto Iterator = Value.begin();
68
69 *Iterator++ = '(';
70 ((Iterator = std::ranges::copy(Signature<TArgs>, Iterator).out), ...);
71 *Iterator++ = ')';
72 Iterator = std::ranges::copy(Signature<TRet>, Iterator).out;
73 *Iterator = '\0';
74
75 return Value;
76 }();
77
78 public:
79 static constexpr FAnsiStringView Value{_Value.GetData(), _Value.Num() - 1};
80 };
81
82 template <typename TRet, typename T, typename... TArgs>
83 struct TSignature<TRet (JNIEnv*, T, TArgs...)>: TSignature<TRet (TArgs...)>
84 {
85 };
86
87 template <typename T, typename... TArgs>
88 struct TConstructor;
89
90 template <typename T, typename U>
91 struct TMember;
92
93 struct FMember
94 {
95 const char* Name;
96 const char* Signature;
97 enum EType
98 {
100 Field,
102 Method
103 }
104 Type;
105 union
106 {
107 jfieldID* FieldId;
109 };
110
111 template <typename T, typename... TArgs>
112 constexpr FMember(TConstructor<T, TArgs...>& Constructor, const char* = nullptr)
113 : Name{"<init>"}
114 , Signature{Jni::Signature<void (TArgs...)>.GetData()}
115 , Type{Method}
117 {
118 }
119
120 template <typename T, typename U> requires std::is_function_v<U>
121 constexpr FMember(TMember<T, U>& Member, const char* _Name)
122 : Name{_Name}
123 , Signature{Jni::Signature<U>.GetData()}
124 , Type{std::is_pointer_v<T> ? Method : StaticMethod}
126 {
127 }
128
129 template <typename T, typename U>
130 constexpr FMember(TMember<T, U>& Member, const char* _Name)
131 : Name{_Name}
132 , Signature{Jni::Signature<U>.GetData()}
133 , Type{std::is_pointer_v<T> ? Field : StaticField}
134 , FieldId{&Member.Value}
135 {
136 }
137 };
138
140
141 namespace Java::Lang
142 {
143 using FClass = std::remove_pointer_t<jclass>;
144 using FObject = std::remove_pointer_t<jobject>;
145 using FString = std::remove_pointer_t<jstring>;
146
147 template <typename T, std::size_t Rank = 1> requires(Rank >= 1)
149 {
150 };
151
152 template <typename T>
153 struct TArray<T, 1>: std::remove_pointer_t<typename TTraits<T>::ArrayType>
154 {
155 };
156
157 template <typename T>
158 struct TClass: FClass
159 {
160 };
161 }
162
163 template <typename T>
164 inline constexpr FAnsiStringView ClassName = T::ClassName;
165
166 template <>
167 inline constexpr FAnsiStringView ClassName<Java::Lang::FClass> = "java/lang/Class";
168
169 template <>
170 inline constexpr FAnsiStringView ClassName<Java::Lang::FObject> = "java/lang/Object";
171
172 template <>
173 inline constexpr FAnsiStringView ClassName<Java::Lang::FString> = "java/lang/String";
174
175 template <typename T>
176 struct TTraits<T*>
177 {
178 private:
179 static constexpr auto _Signature = []
180 {
182 auto Iterator = Value.begin();
183
184 *Iterator++ = 'L';
185 Iterator = std::ranges::copy(ClassName<T>, Iterator).out;
186 *Iterator++ = ';';
187 *Iterator = '\0';
188
189 return Value;
190 }();
191
192 public:
193 static constexpr FAnsiStringView Signature{_Signature.GetData(), _Signature.Num() - 1};
194 using ArrayType = jobjectArray;
195 };
196
197 template <>
198 struct TTraits<void>
199 {
200 static constexpr FAnsiStringView Signature = "V";
201 };
202
203 template <>
204 struct TTraits<jboolean>
205 {
206 static constexpr FAnsiStringView Signature = "Z";
207 using ArrayType = jbooleanArray;
208 };
209
210 template <>
211 struct TTraits<jbyte>
212 {
213 static constexpr FAnsiStringView Signature = "B";
214 using ArrayType = jbyteArray;
215 };
216
217 template <>
218 struct TTraits<jchar>
219 {
220 static constexpr FAnsiStringView Signature = "C";
221 using ArrayType = jcharArray;
222 };
223
224 template <>
225 struct TTraits<jshort>
226 {
227 static constexpr FAnsiStringView Signature = "S";
228 using ArrayType = jshortArray;
229 };
230
231 template <>
232 struct TTraits<jint>
233 {
234 static constexpr FAnsiStringView Signature = "I";
235 using ArrayType = jintArray;
236 };
237
238 template <>
239 struct TTraits<jlong>
240 {
241 static constexpr FAnsiStringView Signature = "J";
242 using ArrayType = jlongArray;
243 };
244
245 template <>
246 struct TTraits<jfloat>
247 {
248 static constexpr FAnsiStringView Signature = "F";
249 using ArrayType = jfloatArray;
250 };
251
252 template <>
253 struct TTraits<jdouble>
254 {
255 static constexpr FAnsiStringView Signature = "D";
256 using ArrayType = jdoubleArray;
257 };
258
259 template <typename T, std::size_t Rank>
260 struct TTraits<Java::Lang::TArray<T, Rank>*>
261 {
262 private:
263 static constexpr auto _Signature = []
264 {
266 auto Iterator = Value.begin();
267
268 Iterator = std::fill_n(Iterator, Rank, '[');
269 Iterator = std::ranges::copy(Signature<T>, Iterator).out;
270 *Iterator = '\0';
271
272 return Value;
273 }();
274
275 public:
276 static constexpr FAnsiStringView Signature{_Signature.GetData(), _Signature.Num() - 1};
277 };
278
279 template <typename T>
280 inline Java::Lang::TClass<T>* Class;
281
282 inline namespace Experimental
283 {
284 template <typename T>
285 struct TInitialize;
286 }
287
288 inline thread_local const struct FEnv
289 {
290 FEnv();
291 FEnv(const FEnv&) = delete;
292 ~FEnv();
293
294 FEnv& operator=(const FEnv&) = delete;
295
296 template <typename T, bool bIsOptional, typename U>
297 void Initialize(Java::Lang::TClass<U>* Class) const
298 {
299 check(Class);
300
301 if constexpr (requires { T::Members; })
302 {
303 bool bResult = Register(Class, T::Members);
304
305 if constexpr (bIsOptional)
306 {
307 if (!bResult)
308 {
309 return;
310 }
311 }
312 else
313 {
314 checkf(bResult, TEXT("Failed to register members for java class: %s"), StringCast<TCHAR>(U::ClassName.GetData()).Get());
315 }
316 }
317
318 if constexpr (requires { T::NativeMethods; })
319 {
320 bool bResult = Register(Class, T::NativeMethods);
321
322 if constexpr (bIsOptional)
323 {
324 if (!bResult)
325 {
326 return;
327 }
328 }
329 else
330 {
331 checkf(bResult, TEXT("Failed to register native methods for java class: %s"), StringCast<TCHAR>(U::ClassName.GetData()).Get());
332 }
333 }
334 }
335
336 template <typename T, bool bIsOptional = requires { requires T::bIsOptional; }>
337 void Initialize() const
338 {
339 if constexpr (std::is_base_of_v<Java::Lang::FObject, T>)
340 {
341 checkf(!Class<T>, TEXT("FEnv::Initialize() called more than once for java class: %s"), StringCast<TCHAR>(T::ClassName.GetData()).Get());
342
344
345 if constexpr (bIsOptional)
346 {
347 if (!LocalClass)
348 {
349 return;
350 }
351 }
352 else
353 {
354 checkf(LocalClass, TEXT("Failed to find java class: %s"), StringCast<TCHAR>(T::ClassName.GetData()).Get());
355 }
356
359 }
360 else
361 {
363 {
364 return;
365 }
366
368 }
369 }
370
371 template <typename T>
372 [[nodiscard]] T* NewGlobalRef(T* Object) const
373 {
374 static_assert(std::is_base_of_v<Java::Lang::FObject, T>); // FIXME needs ndk r28+, should be std::is_pointer_interconvertible_base_of_v
375
376 return reinterpret_cast<T*>(Value->NewGlobalRef(Object));
377 }
378
379 template <typename T>
381 {
383 }
384
385 template <typename U, typename T>
386 [[nodiscard]] TMember<T, U> GetStatic(Java::Lang::TClass<T>* Class, const char* Name) const
387 {
388 if constexpr (std::is_function_v<U>)
389 {
390 jmethodID MethodId = Value->GetStaticMethodID(Class, Name, Signature<U>.GetData());
391
392 if (!MethodId)
393 {
394 Value->ExceptionClear();
395 }
396
397 return {MethodId};
398 }
399 else
400 {
401 jfieldID FieldId = Value->GetStaticFieldID(Class, Name, Signature<U>.GetData());
402
403 if (!FieldId)
404 {
405 Value->ExceptionClear();
406 }
407
408 return {FieldId};
409 }
410 }
411
412 template <typename U, typename T>
413 [[nodiscard]] TMember<T*, U> Get(Java::Lang::TClass<T>* Class, const char* Name) const
414 {
415 if constexpr (std::is_function_v<U>)
416 {
418
419 if (!MethodId)
420 {
421 Value->ExceptionClear();
422 }
423
424 return {MethodId};
425 }
426 else
427 {
428 jfieldID FieldId = Value->GetFieldID(Class, Name, Signature<U>.GetData());
429
430 if (!FieldId)
431 {
432 Value->ExceptionClear();
433 }
434
435 return {FieldId};
436 }
437 }
438
439 [[nodiscard]] FScopedJavaObject<jclass> FindClass(const char* ClassName) const;
440 bool Register(jclass Class, TArrayView<const FMember> Members) const;
442
443 [[nodiscard]] JNIEnv* Get() const
444 {
445 return Value;
446 }
447
448 JNIEnv* operator->() const
449 {
450 return Value;
451 }
452
453 operator JNIEnv*() const
454 {
455 return Value;
456 }
457
458 private:
459 friend void AndroidJavaEnv::InitializeJavaEnv();
460 template <typename T>
461 friend struct TInitialize;
462
463 static void (*InitializeChain)();
464
465 JNIEnv* Value;
466 bool bAttached;
467
468 void Initialize() const;
469 }
470 Env;
471
472 inline void (*FEnv::InitializeChain)() = []
473 {
474 Env.Initialize();
475 };
476
477 inline namespace Experimental
478 {
479 template <typename T>
480 struct TInitialize
481 {
482 private:
483 inline static void (*const Chain)() = std::exchange(FEnv::InitializeChain, []
484 {
485 Chain();
486
487 Env.Initialize<T>();
488 });
489 };
490 }
491
492 template <typename T, typename... TArgs>
493 struct TConstructor
494 {
495 jmethodID Value = nullptr;
496
497 [[nodiscard]] FScopedJavaObject<T*> operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
498 {
499 check(Value);
500 return FScopedJavaObject<T*>{Env->NewObject(Class, Value, args...)};
501 }
502 };
503
504 template <typename T, typename U>
505 struct TMember<T, U*>
506 {
507 jfieldID Value = nullptr;
508
509 [[nodiscard]] FScopedJavaObject<U*> Get(Java::Lang::TClass<T>* Class) const
510 {
511 check(Value);
512 jobject Result = Env->GetStaticObjectField(Class, Value);
513 return !Env->ExceptionCheck() ? FScopedJavaObject<U*>{Result} : nullptr;
514 }
515 void Set(Java::Lang::TClass<T>* Class, U* arg) const
516 {
517 check(Value);
518 Env->SetStaticObjectField(Class, Value, arg);
519 }
520 };
521
522 template <typename T>
523 struct TMember<T, jboolean>
524 {
525 jfieldID Value = nullptr;
526
527 [[nodiscard]] jboolean Get(Java::Lang::TClass<T>* Class) const
528 {
529 check(Value);
530 return Env->GetStaticBooleanField(Class, Value);
531 }
532 void Set(Java::Lang::TClass<T>* Class, jboolean arg) const
533 {
534 check(Value);
535 Env->SetStaticBooleanField(Class, Value, arg);
536 }
537 };
538
539 template <typename T>
540 struct TMember<T, jbyte>
541 {
542 jfieldID Value = nullptr;
543
544 [[nodiscard]] jbyte Get(Java::Lang::TClass<T>* Class) const
545 {
546 check(Value);
547 return Env->GetStaticByteField(Class, Value);
548 }
549 void Set(Java::Lang::TClass<T>* Class, jbyte arg) const
550 {
551 check(Value);
552 Env->SetStaticByteField(Class, Value, arg);
553 }
554 };
555
556 template <typename T>
557 struct TMember<T, jchar>
558 {
559 jfieldID Value = nullptr;
560
561 [[nodiscard]] jchar Get(Java::Lang::TClass<T>* Class) const
562 {
563 check(Value);
564 return Env->GetStaticCharField(Class, Value);
565 }
566 void Set(Java::Lang::TClass<T>* Class, jchar arg) const
567 {
568 check(Value);
569 Env->SetStaticCharField(Class, Value, arg);
570 }
571 };
572
573 template <typename T>
574 struct TMember<T, jshort>
575 {
576 jfieldID Value = nullptr;
577
578 [[nodiscard]] jshort Get(Java::Lang::TClass<T>* Class) const
579 {
580 check(Value);
581 return Env->GetStaticShortField(Class, Value);
582 }
583 void Set(Java::Lang::TClass<T>* Class, jshort arg) const
584 {
585 check(Value);
586 Env->SetStaticShortField(Class, Value, arg);
587 }
588 };
589
590 template <typename T>
591 struct TMember<T, jint>
592 {
593 jfieldID Value = nullptr;
594
595 [[nodiscard]] jint Get(Java::Lang::TClass<T>* Class) const
596 {
597 check(Value);
598 return Env->GetStaticIntField(Class, Value);
599 }
600 void Set(Java::Lang::TClass<T>* Class, jint arg) const
601 {
602 check(Value);
603 Env->SetStaticIntField(Class, Value, arg);
604 }
605 };
606
607 template <typename T>
608 struct TMember<T, jlong>
609 {
610 jfieldID Value = nullptr;
611
612 [[nodiscard]] jlong Get(Java::Lang::TClass<T>* Class) const
613 {
614 check(Value);
615 return Env->GetStaticLongField(Class, Value);
616 }
617 void Set(Java::Lang::TClass<T>* Class, jlong arg) const
618 {
619 check(Value);
620 Env->SetStaticLongField(Class, Value, arg);
621 }
622 };
623
624 template <typename T>
625 struct TMember<T, jfloat>
626 {
627 jfieldID Value = nullptr;
628
629 [[nodiscard]] jfloat Get(Java::Lang::TClass<T>* Class) const
630 {
631 check(Value);
632 return Env->GetStaticFloatField(Class, Value);
633 }
634 void Set(Java::Lang::TClass<T>* Class, jfloat arg) const
635 {
636 check(Value);
637 Env->SetStaticFloatField(Class, Value, arg);
638 }
639 };
640
641 template <typename T>
642 struct TMember<T, jdouble>
643 {
644 jfieldID Value = nullptr;
645
646 [[nodiscard]] jdouble Get(Java::Lang::TClass<T>* Class) const
647 {
648 check(Value);
649 return Env->GetStaticDoubleField(Class, Value);
650 }
651 void Set(Java::Lang::TClass<T>* Class, jdouble arg) const
652 {
653 check(Value);
654 Env->SetStaticDoubleField(Class, Value, arg);
655 }
656 };
657
658 template <typename T, typename U>
659 struct TMember<T*, U*>
660 {
661 jfieldID Value = nullptr;
662
664 {
665 check(Value);
666 jobject Result = Env->GetObjectField(Object, Value);
667 return !Env->ExceptionCheck() ? FScopedJavaObject<U*>{Result} : nullptr;
668 }
669 void Set(T* Object, U* arg) const
670 {
671 check(Value);
672 Env->SetObjectField(Object, Value, arg);
673 }
674 };
675
676 template <typename T>
677 struct TMember<T*, jboolean>
678 {
679 jfieldID Value = nullptr;
680
681 [[nodiscard]] jboolean Get(T* Object) const
682 {
683 check(Value);
684 return Env->GetBooleanField(Object, Value);
685 }
686 void Set(T* Object, jboolean arg) const
687 {
688 check(Value);
689 Env->SetBooleanField(Object, Value, arg);
690 }
691 };
692
693 template <typename T>
694 struct TMember<T*, jbyte>
695 {
696 jfieldID Value = nullptr;
697
698 [[nodiscard]] jbyte Get(T* Object) const
699 {
700 check(Value);
701 return Env->GetByteField(Object, Value);
702 }
703 void Set(T* Object, jbyte arg) const
704 {
705 check(Value);
706 Env->SetByteField(Object, Value, arg);
707 }
708 };
709
710 template <typename T>
711 struct TMember<T*, jchar>
712 {
713 jfieldID Value = nullptr;
714
715 [[nodiscard]] jchar Get(T* Object) const
716 {
717 check(Value);
718 return Env->GetCharField(Object, Value);
719 }
720 void Set(T* Object, jchar arg) const
721 {
722 check(Value);
723 Env->SetCharField(Object, Value, arg);
724 }
725 };
726
727 template <typename T>
728 struct TMember<T*, jshort>
729 {
730 jfieldID Value = nullptr;
731
732 [[nodiscard]] jshort Get(T* Object) const
733 {
734 check(Value);
735 return Env->GetShortField(Object, Value);
736 }
737 void Set(T* Object, jshort arg) const
738 {
739 check(Value);
740 Env->SetShortField(Object, Value, arg);
741 }
742 };
743
744 template <typename T>
745 struct TMember<T*, jint>
746 {
747 jfieldID Value = nullptr;
748
749 [[nodiscard]] jint Get(T* Object) const
750 {
751 check(Value);
752 return Env->GetIntField(Object, Value);
753 }
754 void Set(T* Object, jint arg) const
755 {
756 check(Value);
757 Env->SetIntField(Object, Value, arg);
758 }
759 };
760
761 template <typename T>
762 struct TMember<T*, jlong>
763 {
764 jfieldID Value = nullptr;
765
766 [[nodiscard]] jlong Get(T* Object) const
767 {
768 check(Value);
769 return Env->GetLongField(Object, Value);
770 }
771 void Set(T* Object, jlong arg) const
772 {
773 check(Value);
774 Env->SetLongField(Object, Value, arg);
775 }
776 };
777
778 template <typename T>
779 struct TMember<T*, jfloat>
780 {
781 jfieldID Value = nullptr;
782
783 [[nodiscard]] jfloat Get(T* Object) const
784 {
785 check(Value);
786 return Env->GetFloatField(Object, Value);
787 }
788 void Set(T* Object, jfloat arg) const
789 {
790 check(Value);
791 Env->SetFloatField(Object, Value, arg);
792 }
793 };
794
795 template <typename T>
796 struct TMember<T*, jdouble>
797 {
798 jfieldID Value = nullptr;
799
800 [[nodiscard]] jdouble Get(T* Object) const
801 {
802 check(Value);
803 return Env->GetDoubleField(Object, Value);
804 }
805 void Set(T* Object, jdouble arg) const
806 {
807 check(Value);
808 Env->SetDoubleField(Object, Value, arg);
809 }
810 };
811
812 template <typename T, typename TRet, typename... TArgs>
813 struct TMember<T, TRet* (TArgs...)>
814 {
815 jmethodID Value = nullptr;
816
817 FScopedJavaObject<TRet*> operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
818 {
819 check(Value);
820 jobject Result = Env->CallStaticObjectMethod(Class, Value, args...);
821 return !Env->ExceptionCheck() ? FScopedJavaObject<TRet*>{Result} : nullptr;
822 }
823 };
824
825 template <typename T, typename... TArgs>
826 struct TMember<T, void (TArgs...)>
827 {
828 jmethodID Value = nullptr;
829
830 void operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
831 {
832 check(Value);
833 Env->CallStaticVoidMethod(Class, Value, args...);
834 }
835 };
836
837 template <typename T, typename... TArgs>
838 struct TMember<T, jboolean (TArgs...)>
839 {
840 jmethodID Value = nullptr;
841
842 jboolean operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
843 {
844 check(Value);
845 return Env->CallStaticBooleanMethod(Class, Value, args...);
846 }
847 };
848
849 template <typename T, typename... TArgs>
850 struct TMember<T, jbyte (TArgs...)>
851 {
852 jmethodID Value = nullptr;
853
854 jbyte operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
855 {
856 check(Value);
857 return Env->CallStaticByteMethod(Class, Value, args...);
858 }
859 };
860
861 template <typename T, typename... TArgs>
862 struct TMember<T, jchar (TArgs...)>
863 {
864 jmethodID Value = nullptr;
865
866 jchar operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
867 {
868 check(Value);
869 return Env->CallStaticCharMethod(Class, Value, args...);
870 }
871 };
872
873 template <typename T, typename... TArgs>
874 struct TMember<T, jshort (TArgs...)>
875 {
876 jmethodID Value = nullptr;
877
878 jshort operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
879 {
880 check(Value);
881 return Env->CallStaticShortMethod(Class, Value, args...);
882 }
883 };
884
885 template <typename T, typename... TArgs>
886 struct TMember<T, jint (TArgs...)>
887 {
888 jmethodID Value = nullptr;
889
890 jint operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
891 {
892 check(Value);
893 return Env->CallStaticIntMethod(Class, Value, args...);
894 }
895 };
896
897 template <typename T, typename... TArgs>
898 struct TMember<T, jlong (TArgs...)>
899 {
900 jmethodID Value = nullptr;
901
902 jlong operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
903 {
904 check(Value);
905 return Env->CallStaticLongMethod(Class, Value, args...);
906 }
907 };
908
909 template <typename T, typename... TArgs>
910 struct TMember<T, jfloat (TArgs...)>
911 {
912 jmethodID Value = nullptr;
913
914 jfloat operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
915 {
916 check(Value);
917 return Env->CallStaticFloatMethod(Class, Value, args...);
918 }
919 };
920
921 template <typename T, typename... TArgs>
922 struct TMember<T, jdouble (TArgs...)>
923 {
924 jmethodID Value = nullptr;
925
926 jdouble operator()(Java::Lang::TClass<T>* Class, TArgs... args) const
927 {
928 check(Value);
929 return Env->CallStaticDoubleMethod(Class, Value, args...);
930 }
931 };
932
933 template <typename T, typename TRet, typename... TArgs>
934 struct TMember<T*, TRet* (TArgs...)>
935 {
936 jmethodID Value = nullptr;
937
938 FScopedJavaObject<TRet*> operator()(T* Object, TArgs... args) const
939 {
940 check(Value);
941 jobject Result = Env->CallObjectMethod(Object, Value, args...);
942 return !Env->ExceptionCheck() ? FScopedJavaObject<TRet*>{Result} : nullptr;
943 }
944 };
945
946 template <typename T, typename... TArgs>
947 struct TMember<T*, void (TArgs...)>
948 {
949 jmethodID Value = nullptr;
950
951 void operator()(T* Object, TArgs... args) const
952 {
953 check(Value);
954 Env->CallVoidMethod(Object, Value, args...);
955 }
956 };
957
958 template <typename T, typename... TArgs>
959 struct TMember<T*, jboolean (TArgs...)>
960 {
961 jmethodID Value = nullptr;
962
963 jboolean operator()(T* Object, TArgs... args) const
964 {
965 check(Value);
966 return Env->CallBooleanMethod(Object, Value, args...);
967 }
968 };
969
970 template <typename T, typename... TArgs>
971 struct TMember<T*, jbyte (TArgs...)>
972 {
973 jmethodID Value = nullptr;
974
975 jbyte operator()(T* Object, TArgs... args) const
976 {
977 check(Value);
978 return Env->CallByteMethod(Object, Value, args...);
979 }
980 };
981
982 template <typename T, typename... TArgs>
983 struct TMember<T*, jchar (TArgs...)>
984 {
985 jmethodID Value = nullptr;
986
987 jchar operator()(T* Object, TArgs... args) const
988 {
989 check(Value);
990 return Env->CallCharMethod(Object, Value, args...);
991 }
992 };
993
994 template <typename T, typename... TArgs>
995 struct TMember<T*, jshort (TArgs...)>
996 {
997 jmethodID Value = nullptr;
998
999 jshort operator()(T* Object, TArgs... args) const
1000 {
1001 check(Value);
1002 return Env->CallShortMethod(Object, Value, args...);
1003 }
1004 };
1005
1006 template <typename T, typename... TArgs>
1007 struct TMember<T*, jint (TArgs...)>
1008 {
1009 jmethodID Value = nullptr;
1010
1011 jint operator()(T* Object, TArgs... args) const
1012 {
1013 check(Value);
1014 return Env->CallIntMethod(Object, Value, args...);
1015 }
1016 };
1017
1018 template <typename T, typename... TArgs>
1019 struct TMember<T*, jlong (TArgs...)>
1020 {
1021 jmethodID Value = nullptr;
1022
1023 jlong operator()(T* Object, TArgs... args) const
1024 {
1025 check(Value);
1026 return Env->CallLongMethod(Object, Value, args...);
1027 }
1028 };
1029
1030 template <typename T, typename... TArgs>
1031 struct TMember<T*, jfloat (TArgs...)>
1032 {
1033 jmethodID Value = nullptr;
1034
1035 jfloat operator()(T* Object, TArgs... args) const
1036 {
1037 check(Value);
1038 return Env->CallFloatMethod(Object, Value, args...);
1039 }
1040 };
1041
1042 template <typename T, typename... TArgs>
1043 struct TMember<T*, jdouble (TArgs...)>
1044 {
1045 jmethodID Value = nullptr;
1046
1047 jdouble operator()(T* Object, TArgs... args) const
1048 {
1049 check(Value);
1050 return Env->CallDoubleMethod(Object, Value, args...);
1051 }
1052 };
1053
1054 namespace Java::Lang
1055 {
1056 struct FClassLoader: FObject
1057 {
1058 static constexpr FAnsiStringView ClassName = "java/lang/ClassLoader";
1059
1060 inline static TMember<FClassLoader*, jclass (jstring)> findClass;
1061
1062 static constexpr FMember Members[]
1063 {
1065 };
1066 };
1067 }
1068}
1069
1070// Helper class that automatically calls DeleteLocalRef on the passed-in Java object when goes out of scope
1071template <typename T> requires std::is_pointer_v<T>
1073{
1074public:
1075 FScopedJavaObject() = default;
1076
1077 constexpr FScopedJavaObject(std::nullptr_t)
1078 {
1079 }
1080
1081 explicit constexpr FScopedJavaObject(T Object)
1082 : ObjRef{Object}
1083 {
1084 }
1085
1086 template <typename U> requires std::is_base_of_v<U, std::remove_pointer_t<T>> // FIXME needs ndk r28+, should be std::is_pointer_interconvertible_base_of_v
1087 explicit constexpr FScopedJavaObject(U* Object)
1089 {
1090 }
1091
1092 template <typename U> requires std::is_base_of_v<std::remove_pointer_t<U>, std::remove_pointer_t<T>> // FIXME needs ndk r28+, should be std::is_pointer_interconvertible_base_of_v
1093 explicit constexpr FScopedJavaObject(FScopedJavaObject<U>&& Object)
1095 {
1096 }
1097
1098 //UE_DEPRECATED(5.7, "Use FScopedJavaObject(T InObjRef) instead.")
1100 : ObjRef{InObjRef}
1101 {
1102 }
1103
1105 : ObjRef{std::exchange(Other.ObjRef, nullptr)}
1106 {
1107 }
1108
1109 FScopedJavaObject(const FScopedJavaObject&) = delete;
1110
1112 {
1113 if (*this)
1114 {
1115 UE::Jni::Env->DeleteLocalRef(ObjRef);
1116 }
1117 }
1118
1120 {
1121 Swap(ObjRef, Other.ObjRef);
1122 return *this;
1123 }
1124
1125 FScopedJavaObject& operator=(const FScopedJavaObject&) = delete;
1126
1127 [[nodiscard]] T Leak()
1128 {
1129 return std::exchange(ObjRef, nullptr);
1130 }
1131
1132 // Returns the underlying JNI pointer
1133 [[nodiscard]] T operator*() const { return ObjRef; }
1134
1135 operator bool() const
1136 {
1137 return ObjRef;
1138 }
1139
1140private:
1141 T ObjRef = nullptr;
1142};
1143
1149template <typename T>
1150//UE_DEPRECATED(5.7, "Use CTAD instead. Example: FScopedJavaObject{InObjRef}.")
1152{
1154}
1155
1156class FJavaHelper
1157{
1158public:
1159 // Converts the java string to FString and calls DeleteLocalRef on the passed-in java string reference
1161
1162 // Converts the java string to FString and calls DeleteGlobalRef on the passed-in java string reference
1164
1165 // Converts the java string to FString, does NOT modify the passed-in java string reference
1167
1168 // Converts FString into a Java string wrapped in FScopedJavaObject
1170
1171 // Converts a TArray<FStringView> into a Java string array wrapped in FScopedJavaObject. FStringView content is expected to be null terminated
1173
1174 // Converts the java objectArray to an array of FStrings. jopbjectArray must be a String[] on the Java side
1176};
1177#endif
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
#define check(expr)
Definition AssertionMacros.h:314
#define checkf(expr, format,...)
Definition AssertionMacros.h:315
UE_FORCEINLINE_HINT FLinearColor operator*(float Scalar, const FLinearColor &Color)
Definition Color.h:473
#define UE_DEPRECATED(Version, Message)
Definition CoreMiscDefines.h:302
#define TEXT(x)
Definition Platform.h:1272
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
return true
Definition ExternalRpcRegistry.cpp:601
s expects dereferenced FString s expects ANSICHAR *or UTF8CHAR s expects ANSICHAR *or UTF8CHAR *but got TCHAR *use ls S expects dereferenced FAnsiString or FUtf8String S expects character pointer but got S expects ANSICHAR *or UTF8CHAR S expects ANSICHAR *or UTF8CHAR *but got TCHAR *use s hs expects dereferenced FAnsiString or FUtf8String hs expects ANSICHAR *or UTF8CHAR hs expects ANSICHAR *or UTF8CHAR *but got TCHAR *use s ls expects character pointer but got ls expects TCHAR ls expects TCHAR *but got ANSICHAR *or UTF8CHAR *use hs c expects ANSICHAR or UTF8CHAR p expects a pointer unsupported format not enough arguments provided to format string d expects integral arg(eg. `char`, `int`, `long`, etc.)") X(ZNeedsIntegerArg
const bool
Definition NetworkReplayStreaming.h:178
auto GetData(const TStringConversion< Converter, DefaultConversionSize > &Conversion) -> decltype(Conversion.Get())
Definition StringConv.h:802
Definition ArrayView.h:139
Definition Array.h:670
Definition StaticArray.h:26
UE_REWRITE constexpr InElementType * begin()
Definition StaticArray.h:99
constexpr const CharType * GetData() const
Definition StringView.h:160
void exchange(FReal &f1, FReal &f2)
Definition FFT.cpp:78
Type
Definition PawnAction_Move.h:11
Definition RobinHoodHashTable.h:18
Definition FieldSystemNoiseAlgo.cpp:6
@ Member
Definition AssetDataTagMap.cpp:938
FORCEINLINE T * Get(const FObjectPtr &ObjectPtr)
Definition ObjectPtr.h:426
UStruct * FindClass(const FReadState &State)
Definition StructDeserializer.cpp:40
args
Definition TestServer.py:519
EType
Definition AccessDetection.h:11
FValue::Object FObject
Definition RapidJsonUtils.h:69
FValue::Member FMember
Definition RapidJsonUtils.h:62
UE_STRING_CLASS Result(Forward< LhsType >(Lhs), RhsLen)
Definition String.cpp.inl:732