The open source OpenXR runtime
1#ifndef _JNIPP_H_
2#define _JNIPP_H_ 1
3
4// Standard Dependencies
5#include <cstring>
6#include <stdexcept> // For std::runtime_error
7#include <string>
8
9// Forward Declarations
10struct JNIEnv_;
11struct _JNIEnv;
12struct JavaVM_;
13struct _JavaVM;
14struct _jmethodID;
15struct _jfieldID;
16class _jobject;
17class _jclass;
18class _jarray;
19
20namespace jni
21{
22 // JNI Base Types
23#ifdef __ANDROID__
24 typedef _JNIEnv JNIEnv;
25 typedef _JavaVM JavaVM;
26#else
27 typedef JNIEnv_ JNIEnv;
28 typedef JavaVM_ JavaVM;
29#endif
30
31 typedef _jobject* jobject;
32 typedef _jclass* jclass;
33 typedef _jarray* jarray;
34
35 /**
36 You can save a method via its handle using Class::getMethod() if it is
37 going to be used often. This saves Object::call() from having to locate
38 the method each time by name.
39
40 Note that these handles are global and do not need to be deleted.
41 */
42 typedef _jmethodID* method_t;
43
44 /**
45 You can save a field via its handle using Class::getField() if it is
46 going to be used often. This saves Object::set() and Object::get() from
47 having to locate the field each time by name.
48
49 Note that these handles are global and do not need to be deleted.
50 */
51 typedef _jfieldID* field_t;
52
53 /**
54 Type used to denote the Java byte type.
55 */
56 typedef unsigned char byte_t;
57
58#ifdef JNIPP_EXCEPTION_CLASS
59
60 /**
61 Base class for thrown Exceptions.
62 */
63 typedef JNIPP_EXCEPTION_CLASS Exception;
64
65#else
66
67 /**
68 Base class for thrown Exceptions.
69 */
70 typedef std::runtime_error Exception;
71
72#endif // JNIPP_EXCEPTION_CLASS
73
74 // Foward Declarations
75 class Object;
76 template <class TElement> class Array;
77
78 /**
79 This namespace is for messy implementation details only. It is not a part
80 of the external API and is subject to change at any time. It is only in a
81 header file due to the fact it is required by some template functions.
82
83 Long story short... this stuff be messy, yo.
84 */
85 namespace internal
86 {
87 /*
88 Signature Generation
89 */
90
91 inline std::string valueSig(const void*) { return "V"; }
92 inline std::string valueSig(const bool*) { return "Z"; }
93 inline std::string valueSig(const byte_t*) { return "B"; }
94 inline std::string valueSig(const wchar_t*) { return "C"; }
95 inline std::string valueSig(const short*) { return "S"; }
96 inline std::string valueSig(const int*) { return "I"; }
97 inline std::string valueSig(const long long*) { return "J"; }
98 inline std::string valueSig(const float*) { return "F"; }
99 inline std::string valueSig(const double*) { return "D"; }
100 inline std::string valueSig(const std::string*) { return "Ljava/lang/String;"; }
101 inline std::string valueSig(const std::wstring*) { return "Ljava/lang/String;"; }
102 inline std::string valueSig(const char* const*) { return "Ljava/lang/String;"; }
103 inline std::string valueSig(const wchar_t* const*) { return "Ljava/lang/String;"; }
104 std::string valueSig(const Object* obj);
105 inline std::string valueSig(const Object* const* obj) { return valueSig(obj ? *obj : nullptr); }
106
107 template <class TArg>
108 inline std::string valueSig(const Array<TArg>*) { return "[" + valueSig((TArg*) nullptr); }
109
110 template <int n, class TArg>
111 inline std::string valueSig(const TArg(*arg)[n]) { return valueSig((const TArg* const*)arg); }
112
113 inline std::string sig() { return ""; }
114
115 template <class TArg, class... TArgs>
116 std::string sig(const TArg& arg, const TArgs&... args) {
117 return valueSig(&arg) + sig(args...);
118 }
119
120 /*
121 Argument Conversion
122 */
123
124 typedef long long value_t;
125
126 void valueArg(value_t* v, bool a);
127 void valueArg(value_t* v, byte_t a);
128 void valueArg(value_t* v, wchar_t a);
129 void valueArg(value_t* v, short a);
130 void valueArg(value_t* v, int a);
131 void valueArg(value_t* v, long long a);
132 void valueArg(value_t* v, float a);
133 void valueArg(value_t* v, double a);
134 void valueArg(value_t* v, jobject a);
135 void valueArg(value_t* v, const Object& a);
136 void valueArg(value_t* v, const Object* const& a);
137 void valueArg(value_t* v, const std::string& a);
138 void valueArg(value_t* v, const char* a);
139 void valueArg(value_t* v, const std::wstring& a);
140 void valueArg(value_t* v, const wchar_t* a);
141 void valueArg(value_t* v, std::nullptr_t);
142
143 inline void args(value_t*) {}
144
145 template <class TArg, class... TArgs>
146 void args(value_t* values, const TArg& arg, const TArgs&... args) {
147 valueArg(values, arg);
148 internal::args(values + 1, args...);
149 }
150
151 template <class TArg> void cleanupArg(value_t* /* value */) {}
152 template <> void cleanupArg<std::string>(value_t* value);
153 template <> void cleanupArg<std::wstring>(value_t* value);
154 template <> void cleanupArg<const char*>(value_t* value);
155 template <> void cleanupArg<const wchar_t*>(value_t* value);
156
157 template <class TArg = void, class... TArgs>
158 void cleanupArgs(value_t* values) {
159 cleanupArg<TArg>(values);
160 cleanupArgs<TArgs...>(values + 1);
161 }
162
163 template <>
164 inline void cleanupArgs<void>(value_t* /* values */) {}
165
166 template <class... TArgs>
167 class ArgArray
168 {
169 public:
170 ArgArray(const TArgs&... args) {
171 std::memset(this, 0, sizeof(ArgArray<TArgs...>));
172 internal::args(values, args...);
173 }
174
175 ~ArgArray() {
176 cleanupArgs<TArgs...>(values);
177 }
178
179 value_t values[sizeof...(TArgs)];
180 };
181
182 /* specialization for empty array - no args. Avoids "empty array" warning. */
183 template <>
184 class ArgArray<>
185 {
186 public:
187 ArgArray() {
188 std::memset(this, 0, sizeof(ArgArray<>));
189 }
190
191 ~ArgArray() {
192 }
193
194 value_t values[1];
195 };
196 long getArrayLength(jarray array);
197
198 /**
199 * @brief Used as a tag type for dispatching internally based on return type.
200 *
201 * @tparam T The type to wrap.
202 */
203 template<typename T>
204 struct ReturnTypeWrapper
205 {
206 using type = T;
207 };
208 }
209
210 /**
211 Initialises the Java Native Interface with the given JNIEnv handle, which
212 gets passed into a native function which is called from Java. This only
213 needs to be done once per process - further calls are no-ops.
214 \param env A JNI environment handle.
215 */
216 void init(JNIEnv* env);
217 /**
218 Initialises the Java Native Interface with the given JavaVM handle,
219 which may be accessible. This (or the other overload) only needs to be
220 done once per process - further calls are no-ops.
221 \param vm A JNI VM handle.
222 */
223 void init(JavaVM* vm);
224
225 /**
226 Get the appropriate JNI environment for this thread.
227 */
228 JNIEnv* env();
229
230 /**
231 Object corresponds with a `java.lang.Object` instance. With an Object,
232 you can then call Java methods, and access fields on the Object. To
233 instantiate an Object of a given class, use the `Class` class.
234 */
235 class Object
236 {
237 public:
238 /** Flags which can be passed to the Object constructor. */
239 enum ScopeFlags
240 {
241 Temporary = 1, ///< Temporary object. Do not create a global reference.
242 DeleteLocalInput = 2 ///< The input reference is temporary and can be deleted.
243 };
244
245 /** Default constructor. Creates a `null` object. */
246 Object() noexcept;
247
248 /**
249 Copies a reference to another Object. Note that this is not a deep
250 copy operation, and both Objects will reference the same Java
251 Object.
252 \param other The Object to copy.
253 */
254 Object(const Object& other);
255
256 /**
257 Move constructor. Copies the Object reference from the supplied
258 Object, and then nulls the supplied Object reference.
259 \param other The Object to move.
260 */
261 Object(Object&& other) noexcept;
262
263 /**
264 Creates an Object from a local JNI reference.
265 \param ref The local JNI reference.
266 \param scopeFlags Bitmask of ScopeFlags values.
267 */
268 Object(jobject ref, int scopeFlags = 0);
269
270 /**
271 Destructor. Releases this reference on the Java Object so it can be
272 picked up by the garbage collector.
273 */
274 virtual ~Object() noexcept;
275
276 /**
277 Assignment operator. Copies the object reference from the supplied
278 Object. They will now both point to the same Java Object.
279 \param other The Object to copy.
280 \return This Object.
281 */
282 Object& operator=(const Object& other);
283
284 /**
285 Assignment operator. Moves the object reference from the supplied
286 Object to this one, and leaves the other one as a null.
287 \param other The Object to move.
288 \return This Object.
289 */
290 Object& operator=(Object&& other);
291
292 /**
293 Tells whether the two Objects refer to the same Java Object.
294 \param other the Object to compare with.
295 \return `true` if the same, `false` otherwise.
296 */
297 bool operator==(const Object& other) const;
298
299 /**
300 Tells whether the two Objects refer to the same Java Object.
301 \param other the Object to compare with.
302 \return `true` if the different, `false` otherwise.
303 */
304 bool operator!=(const Object& other) const { return !operator==(other); }
305
306 /**
307 Calls the given method on this Object. The method should have no
308 parameters. Note that the return type should be explicitly stated
309 in the function call.
310 \param method A method handle which applies to this Object.
311 \return The method's return value.
312 */
313 template <class TReturn>
314 TReturn call(method_t method) const { return callMethod(method, nullptr, internal::ReturnTypeWrapper<TReturn>{}); }
315
316 /**
317 Calls the method on this Object with the given name, and no arguments.
318 Note that the return type should be explicitly stated in the function
319 call.
320 \param name The name of the method to call (with optional signature).
321 \return The method's return value.
322 */
323 template <class TReturn>
324 TReturn call(const char* name) const {
325 if (std::strstr(name, "()"))
326 return call<TReturn>(getMethod(name));
327
328 // No signature supplied. Generate our own.
329 method_t method = getMethod(name, ("()" + internal::valueSig((TReturn*) nullptr)).c_str());
330 return call<TReturn>(method);
331 }
332
333 /**
334 Calls the method on this Object and supplies the given arguments.
335 Note that the return type should be explicitly stated in the function
336 call.
337 \param method The method to call.
338 \param args Arguments to supply to the method.
339 \return The method's return value.
340 */
341 template <class TReturn, class... TArgs>
342 TReturn call(method_t method, const TArgs&... args) const {
343 internal::ArgArray<TArgs...> transform(args...);
344 return callMethod(method, transform.values, internal::ReturnTypeWrapper<TReturn>{});
345 }
346
347 /**
348 Calls the method on this Object and supplies the given arguments.
349 Note that the return type should be explicitly stated in the function
350 call. The type signature of the method is calculated by the types of
351 the supplied arguments.
352 \param name The name of the method to call (and optional signature).
353 \param args Arguments to supply to the method.
354 \return The method's return value.
355 */
356 template <class TReturn, class... TArgs>
357 TReturn call(const char* name, const TArgs&... args) const {
358 if (std::strchr(name, '('))
359 return call<TReturn>(getMethod(name), args...);
360
361 std::string sig = "(" + internal::sig(args...) + ")" + internal::valueSig((TReturn*) nullptr);
362 method_t method = getMethod(name, sig.c_str());
363 return call<TReturn>(method, args...);
364 }
365
366 /**
367 Gets a field value from this Object. The field must belong to the
368 Object's class. Note that the field type should be explicitly stated
369 in the function call.
370 \param field Identifier for the field to retrieve.
371 \return The field's value.
372 */
373 template <class TType>
374 TType get(field_t field) const {
375 // If you get a compile error here, then you've asked for a type
376 // we don't know how to get from JNI directly.
377 return getFieldValue(field, internal::ReturnTypeWrapper<TType>{});
378 }
379
380 /**
381 Gets a field value from this Object. The field must belong to the
382 Object's class. Note that the field type should be explicitly stated
383 in the function call.
384 \param name The name of the field to retrieve.
385 \return The field's value.
386 */
387 template <class TType>
388 TType get(const char* name) const {
389 field_t field = getField(name, internal::valueSig((TType*) nullptr).c_str());
390 return get<TType>(field);
391 }
392
393 /**
394 Sets a field's value on this Object. The field must belong to the
395 Object's class, and the parameter's type should correspond to the
396 type of the field.
397 \param field The field to set the value to.
398 \param value The value to set.
399 */
400 template <class TType>
401 void set(field_t field, const TType& value);
402
403 /**
404 Sets a field's value on this Object. The field must belong to the
405 Object's class, and the parameter's type should correspond to the
406 type of the field.
407 \param name The name of the field to set the value to.
408 \param value The value to set.
409 */
410 template <class TType>
411 void set(const char* name, const TType& value) {
412 field_t field = getField(name, internal::valueSig((TType*) nullptr).c_str());
413 set(field, value);
414 }
415
416 /**
417 Tells whether this Object is currently a `null` pointer.
418 \return `true` if `null`, `false` if it references an object.
419 */
420 bool isNull() const noexcept;
421
422 /**
423 Gets a handle for this Object's class. Ideally, this should just return a Class,
424 but C++ won't let us do that that.
425 \return The Object's Class's handle.
426 */
427 jclass getClass() const;
428
429 /**
430 Gets the underlying JNI jobject handle.
431 \return The JNI handle.
432 */
433 jobject getHandle() const noexcept { return _handle; }
434
435 /**
436 Create a local reference for the underlying JNI handle.
437 \return The local reference.
438 */
439 jobject makeLocalReference() const;
440
441 private:
442 // Helper Functions
443 method_t getMethod(const char* name, const char* signature) const;
444 method_t getMethod(const char* nameAndSignature) const;
445 field_t getField(const char* name, const char* signature) const;
446
447 void callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<void> const&) const;
448 bool callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<bool> const&) const;
449 byte_t callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<byte_t> const&) const;
450 wchar_t callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<wchar_t> const&) const;
451 short callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<short> const&) const;
452 int callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<int> const&) const;
453 long long callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<long long> const&) const;
454 float callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<float> const&) const;
455 double callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<double> const&) const;
456 std::string callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<std::string> const&) const;
457 std::wstring callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<std::wstring> const&) const;
458 jni::Object callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<jni::Object> const&) const;
459 jarray callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<jarray> const&) const;
460
461 template<typename T>
462 jni::Array<T> callMethod(method_t method, internal::value_t* args, internal::ReturnTypeWrapper<jni::Array<T>> const&) const;
463
464 void getFieldValue(field_t field, internal::ReturnTypeWrapper<void> const&) const;
465 bool getFieldValue(field_t field, internal::ReturnTypeWrapper<bool> const&) const;
466 byte_t getFieldValue(field_t field, internal::ReturnTypeWrapper<byte_t> const&) const;
467 wchar_t getFieldValue(field_t field, internal::ReturnTypeWrapper<wchar_t> const&) const;
468 short getFieldValue(field_t field, internal::ReturnTypeWrapper<short> const&) const;
469 int getFieldValue(field_t field, internal::ReturnTypeWrapper<int> const&) const;
470 long long getFieldValue(field_t field, internal::ReturnTypeWrapper<long long> const&) const;
471 float getFieldValue(field_t field, internal::ReturnTypeWrapper<float> const&) const;
472 double getFieldValue(field_t field, internal::ReturnTypeWrapper<double> const&) const;
473 std::string getFieldValue(field_t field, internal::ReturnTypeWrapper<std::string> const&) const;
474 std::wstring getFieldValue(field_t field, internal::ReturnTypeWrapper<std::wstring> const&) const;
475 jni::Object getFieldValue(field_t field, internal::ReturnTypeWrapper<jni::Object> const&) const;
476
477 // Instance Variables
478 jobject _handle;
479 mutable jclass _class;
480 bool _isGlobal;
481 };
482
483 /**
484 Class corresponds with `java.lang.Class`, and allows you to instantiate
485 Objects and get class members such as methods and fields.
486 */
487 class Class : protected Object
488 {
489 public:
490 /**
491 Creates a null class reference.
492 */
493 Class() : Object() {}
494
495 /**
496 Obtains a class reference to the Java class with the given qualified
497 name.
498 \param name The qualified class name (e.g. "java/lang/String").
499 */
500 Class(const char* name);
501
502 /**
503 Creates a Class object by JNI reference.
504 \param ref The JNI class reference.
505 \param scopeFlags Bitmask of Object::ScopeFlags.
506 */
507 Class(jclass ref, int scopeFlags = Temporary);
508
509 /**
510 Tells whether this Class is null or valid.
511 \return `true` if null, `false` if valid.
512 */
513 bool isNull() const noexcept { return Object::isNull(); }
514
515 /**
516 Creates a new instance of this Java class and returns a reference to
517 it. The item's parameterless constructor is called.
518 \return The created instance.
519 */
520 Object newInstance() const;
521
522 /**
523 Creates a new instance of this Java class and returns a reference to
524 it.
525 \param constructor The constructor to call.
526 \param args Arguments to supply to the constructor.
527 \return The created instance.
528 */
529 template <class... TArgs>
530 Object newInstance(method_t constructor, const TArgs&... args) const {
531 internal::ArgArray<TArgs...> transform(args...);
532 return newObject(constructor, transform.values);
533 }
534
535 /**
536 Creates a new instance of this Java class and returns a reference to
537 it. The constructor signature is determined by the supplied parameters,
538 and the parameters are then passed to the constructor.
539 \param args Arguments to supply to the constructor.
540 \return The created instance.
541 */
542 template <class... TArgs>
543 Object newInstance(const TArgs&... args) const {
544 method_t constructor = getMethod("<init>", ("(" + internal::sig(args...) + ")V").c_str());
545 return newInstance(constructor, args...);
546 }
547
548 /**
549 Gets a handle to the field with the given name and type signature.
550 This handle can then be stored so that the field does not need to
551 be looked up by name again. It does not need to be deleted.
552 \param name The name of the field.
553 \param signature The JNI type signature of the field.
554 \return The field ID.
555 */
556 field_t getField(const char* name, const char* signature) const;
557
558 /**
559 Gets a handle to the field with the given name and the supplied type.
560 This handle can then be stored so that the field does not need to
561 be looked up by name again. It does not need to be deleted.
562 \param name The name of the field.
563 \return The field ID.
564 */
565 template<typename TType>
566 field_t getField(const char* name) const {
567 return getField(name, internal::valueSig((TType*) nullptr).c_str());
568 }
569
570 /**
571 Gets a handle to the static field with the given name and type signature.
572 This handle can then be stored so that the field does not need to
573 be looked up by name again. It does not need to be deleted.
574 \param name The name of the field.
575 \param signature The JNI type signature of the field.
576 \return The field ID.
577 */
578 field_t getStaticField(const char* name, const char* signature) const;
579
580 /**
581 Gets a handle to the static field with the given name and the supplied type.
582 This handle can then be stored so that the field does not need to
583 be looked up by name again. It does not need to be deleted.
584 \param name The name of the field.
585 \return The field ID.
586 */
587 template<typename TType>
588 field_t getStaticField(const char* name) const {
589 return getStaticField(name, internal::valueSig((TType*)nullptr).c_str());
590 }
591
592 /**
593 Gets a handle to the method with the given name and signature.
594 This handle can then be stored so that the method does not need
595 to be looked up by name again. It does not need to be deleted.
596 \param name The name of the method.
597 \param signature The JNI method signature.
598 \return The method ID.
599 */
600 method_t getMethod(const char* name, const char* signature) const;
601
602 /**
603 Gets a handle to the method with the given name and signature.
604 This handle can then be stored so that the method does not need
605 to be looked up by name again. It does not need to be deleted.
606 \param nameAndSignature Name and signature identifier (e.g. "toString()Ljava/lang/String;").
607 \return The method ID.
608 */
609 method_t getMethod(const char* nameAndSignature) const;
610
611 /**
612 Gets a handle to the static method with the given name and signature.
613 This handle can then be stored so that the method does not need
614 to be looked up by name again. It does not need to be deleted.
615 \param name The name of the method.
616 \param signature The JNI method signature.
617 \return The method ID.
618 */
619 method_t getStaticMethod(const char* name, const char* signature) const;
620
621 /**
622 Gets a handle to the static method with the given name and signature.
623 This handle can then be stored so that the method does not need
624 to be looked up by name again. It does not need to be deleted.
625 \param nameAndSignature Name and signature identifier (e.g. "toString()Ljava/lang/String;").
626 \return The method ID.
627 */
628 method_t getStaticMethod(const char* nameAndSignature) const;
629
630 /**
631 Gets a handle to the constructor for this Class with the given
632 signature. Note that the return type should always be `void` ("V").
633 \param signature The JNI method signature for the constructor.
634 \return The constructor method ID.
635 */
636 method_t getConstructor(const char* signature) const { return getMethod("<init>", signature); }
637
638 /**
639 Gets the parent Class of this Class.
640 \return The parent class.
641 */
642 Class getParent() const;
643
644 /**
645 Gets the JNI-qualified name of this Class.
646 \return The Class name.
647 */
648 std::string getName() const;
649
650 /**
651 Calls a static method on this Class. The method should have no
652 parameters. Note that the return type should be explicitly stated
653 in the function call.
654 \param method A method handle which applies to this Object.
655 \return The method's return value.
656 */
657 template <class TReturn>
658 TReturn call(method_t method) const { return callStaticMethod<TReturn>(method, nullptr); }
659
660 /**
661 Calls a static method on this Class with the given name, and no arguments.
662 Note that the return type should be explicitly stated in the function
663 call.
664 \param name The name of the method to call.
665 \return The method's return value.
666 */
667 template <class TReturn>
668 TReturn call(const char* name) const {
669 method_t method = getStaticMethod(name, ("()" + internal::valueSig((TReturn*) nullptr)).c_str());
670 return call<TReturn>(method);
671 }
672
673 /**
674 Calls a static method on this Class and supplies the given arguments.
675 Note that the return type should be explicitly stated in the function
676 call.
677 \param method The method to call.
678 \param args Arguments to supply to the method.
679 \return The method's return value.
680 */
681 template <class TReturn, class... TArgs>
682 TReturn call(method_t method, const TArgs&... args) const {
683 internal::ArgArray<TArgs...> transform(args...);
684 return callStaticMethod<TReturn>(method, transform.values);
685 }
686
687 /**
688 Calls a static method on this Class and supplies the given arguments.
689 Note that the return type should be explicitly stated in the function
690 call. The type signature of the method is calculated by the types of
691 the supplied arguments.
692 \param name The name of the method to call.
693 \param args Arguments to supply to the method.
694 \return The method's return value.
695 */
696 template <class TReturn, class... TArgs>
697 TReturn call(const char* name, const TArgs&... args) const {
698 if (std::strchr(name, '('))
699 return call<TReturn>(getStaticMethod(name), args...);
700
701 std::string sig = "(" + internal::sig(args...) + ")" + internal::valueSig((TReturn*) nullptr);
702 method_t method = getStaticMethod(name, sig.c_str());
703 return call<TReturn>(method, args...);
704 }
705
706 /**
707 Calls a non-static method on this Class, applying it to the supplied
708 Object. The difference between this and Object.call() is that the
709 specific class implementation of the method is called, rather than
710 doing a virtual method lookup.
711 \param obj The Object to call the method on.
712 \param method The method to call.
713 \return The method's return value.
714 */
715 template <class TReturn>
716 TReturn call(const Object& obj, method_t method) const {
717 return callExactMethod<TReturn>(obj.getHandle(), method, nullptr);
718 }
719
720 /**
721 Calls a non-static method on this Class, applying it to the supplied
722 Object. The difference between this and Object.call() is that the
723 specific class implementation of the method is called, rather than
724 doing a virtual method lookup.
725 \param obj The Object to call the method on.
726 \param name The name of the method to call.
727 \return The method's return value.
728 */
729 template <class TReturn>
730 TReturn call(const Object& obj, const char* name) const {
731 method_t method = getMethod(name, ("()" + internal::valueSig((TReturn*) nullptr)).c_str());
732 return call<TReturn>(obj, method);
733 }
734 template <class TReturn>
735 TReturn call(const Object* obj, const char* name) const {
736 return call<TReturn>(obj, name);
737 }
738
739 /**
740 Calls a non-static method on this Class, applying it to the supplied
741 Object. The difference between this and Object.call() is that the
742 specific class implementation of the method is called, rather than
743 doing a virtual method lookup.
744 \param obj The Object to call the method on.
745 \param method The method to call.
746 \param args Arguments to pass to the method.
747 \return The method's return value.
748 */
749 template <class TReturn, class... TArgs>
750 TReturn call(const Object& obj, method_t method, const TArgs&... args) const {
751 internal::ArgArray<TArgs...> transform(args...);
752 return callExactMethod<TReturn>(obj.getHandle(), method, transform.values);
753 }
754 template <class TReturn, class... TArgs>
755 TReturn call(const Object* obj, method_t method, const TArgs&... args) const {
756 return call<TReturn>(*obj, method, args...);
757 }
758
759 /**
760 Calls a non-static method on this Class, applying it to the supplied
761 Object. The difference between this and Object.call() is that the
762 specific class implementation of the method is called, rather than
763 doing a virtual method lookup.
764 \param obj The Object to call the method on.
765 \param name The name of the method to call.
766 \param args Arguments to pass to the method.
767 \return The method's return value.
768 */
769 template <class TReturn, class... TArgs>
770 TReturn call(const Object& obj, const char* name, const TArgs&... args) const {
771 std::string sig = "(" + internal::sig(args...) + ")" + internal::valueSig((TReturn*) nullptr);
772 method_t method = getMethod(name, sig.c_str());
773 return call<TReturn>(obj, method, args...);
774 }
775 template <class TReturn, class... TArgs>
776 TReturn call(const Object* obj, const char* name, const TArgs&... args) const {
777 return call<TReturn>(*obj, name, args...);
778 }
779
780 /**
781 Gets a static field value from this Class. Note that the field type
782 should be explicitly stated in the function call.
783 \param field Identifier for the field to retrieve.
784 \return The field's value.
785 */
786 template <class TType>
787 TType get(field_t field) const;
788
789 /**
790 Gets a static field value from this Class. Note that the field type
791 should be explicitly stated in the function call.
792 \param name The name of the field to retrieve.
793 \return The field's value.
794 */
795 template <class TType>
796 TType get(const char* name) const {
797 field_t field = getStaticField(name, internal::valueSig((TType*) nullptr).c_str());
798 return get<TType>(field);
799 }
800
801 /**
802 Sets a static field's value on this Class. The parameter's type should
803 correspond to the type of the field.
804 \param field The field to set the value to.
805 \param value The value to set.
806 */
807 template <class TType>
808 void set(field_t field, const TType& value);
809
810 /**
811 Sets a static field's value on this Class. The parameter's type
812 should correspond to the type of the field.
813 \param name The name of the field to set the value to.
814 \param value The value to set.
815 */
816 template <class TType>
817 void set(const char* name, const TType& value) {
818 field_t field = getStaticField(name, internal::valueSig((TType*) nullptr).c_str());
819 set(field, value);
820 }
821
822 /**
823 Gets the underlying JNI jclass handle.
824 \return The JNI handle.
825 */
826 jclass getHandle() const noexcept { return jclass(Object::getHandle()); }
827
828 private:
829 // Helper Functions
830 template <class TType> TType callStaticMethod(method_t method, internal::value_t* values) const;
831 template <class TType> TType callExactMethod(jobject obj, method_t method, internal::value_t* values) const;
832 Object newObject(method_t constructor, internal::value_t* args) const;
833 };
834
835 /**
836 Convenience class for dealing with Java enums.
837 */
838 class Enum : protected Class
839 {
840 public:
841 /**
842 Loads the Enum with the given JNI-formatted name.
843 \param name The name of the enum.
844 */
845 Enum(const char* name);
846
847 /**
848 Gets the enum value with the given name.
849 \param name The name of the enum value.
850 \return The enum value identifier.
851 */
852 Object get(const char* name) const;
853
854 private:
855 // Instance Variables
856 std::string _name;
857 };
858
859 /**
860 Used to interact with native Java arrays. The element type can be any primitive
861 type, jni::Object, std::string or std::wstring.
862 */
863 template <class TElement>
864 class Array : public Object
865 {
866 public:
867 /**
868 Default constructor. Creates a null array reference.
869 */
870 Array() noexcept;
871
872 /**
873 Creates a Array object by JNI reference.
874 \param ref The JNI array reference.
875 \param scopeFlags Bitmask of Object::ScopeFlags.
876 */
877 Array(jarray ref, int scopeFlags = Temporary);
878
879 /**
880 Creates an Array of the given length. The elements are default initialised
881 to zero / null values.
882 \param length The Array length.
883 */
884 Array(long length);
885
886 /**
887 Creates an Array of the given length. A Class type is also specified, but can
888 be left null to default to "java.lang.Object".
889 \param length The Array length.
890 \param type The element type.
891
892 */
893 Array(long length, const Class& type);
894
895 /**
896 Copy constructor. Shares a reference to the Java array with the
897 copied Array object.
898 \param other The Array to copy.
899 */
900 Array(const Array<TElement>& other);
901
902 /**
903 Move constructor. Moves the array reference to the new Array, and leaves
904 the previous Array as a null reference.
905 \param other The Array to move.
906 */
907 Array(Array<TElement>&& other) noexcept;
908
909 /**
910 Assignment operator. Copies the array reference from the supplied
911 Array. They will now both point to the same Java array.
912 \param other The Array to copy.
913 \return This Array.
914 */
915 Array<TElement>& operator=(const Array<TElement>& other);
916
917 /**
918 Assignment operator. Moves the array reference from the supplied
919 Array to this one, and leaves the other one as a null.
920 \param other The Array to move.
921 \return This Array.
922 */
923 Array<TElement>& operator=(Array<TElement>&& other);
924
925 /**
926 Checks whether these Arrays both reference the same java array.
927 \param other The Array to compare with.
928 \return true if the same (or both null), false otherwise.
929 */
930 bool operator==(const Array<TElement>& other) const { return Object::operator==(other); }
931
932 /**
933 Checks whether these Arrays reference different the java arrays.
934 \param other The Array to compare with.
935 \return false if the same (or both null), true otherwise.
936 */
937 bool operator!=(const Array<TElement>& other) const { return !operator==(other); }
938
939 /**
940 Sets the element value at the given index in the Array.
941 \param index The zero-based index.
942 \param value The value to set.
943 */
944 void setElement(long index, TElement value);
945
946 /**
947 Gets the value at the given index within the Array.
948 \param index The zero-based index.
949 \return The element at the given index.
950 */
951 TElement getElement(long index) const;
952 TElement operator[](long index) const { return getElement(index); }
953
954 /**
955 Gets the length of this Array.
956 \return The array length.
957 */
958 long getLength() const;
959
960 /**
961 Gets the underlying JNI jarray handle.
962 \return The JNI handle.
963 */
964 jarray getHandle() const noexcept { return jarray(Object::getHandle()); }
965
966 private:
967 // Instance Variables
968 mutable long _length; ///< Mutable as it may only finally get set in a getLength() call.
969 };
970
971 /**
972 When the application's entry point is in C++ rather than in Java, it will
973 need to spin up its own instance of the Java Virtual Machine (JVM) before
974 it can initialize the Java Native Interface. Vm is used to create and
975 destroy a running JVM instance.
976
977 It uses the RAII idiom, so when the destructor is called, the Vm is shut
978 down.
979
980 Note that currently only one instance is supported. Attempts to create
981 more will result in an InitializationException.
982 */
983 class Vm final
984 {
985 public:
986 /**
987 Starts the Java Virtual Machine.
988 \param path The path to the jvm.dll (or null for auto-detect).
989 */
990 Vm(const char* path = nullptr);
991
992 /** Destroys the running instance of the JVM. */
993 ~Vm();
994 };
995
996 /**
997 A Java method call threw an Exception.
998 */
999 class InvocationException : public Exception
1000 {
1001 public:
1002 /**
1003 Constructor with an error message.
1004 \param msg Message to pass to the Exception.
1005 */
1006 InvocationException(const char* msg = "Java Exception detected") : Exception(msg) {}
1007 };
1008
1009 /**
1010 A supplied name or type signature could not be resolved.
1011 */
1012 class NameResolutionException : public Exception
1013 {
1014 public:
1015 /**
1016 Constructor with an error message.
1017 \param name The name of the unresolved symbol.
1018 */
1019 NameResolutionException(const char* name) : Exception(name) {}
1020 };
1021
1022 /**
1023 The Java Native Interface was not properly initialized.
1024 */
1025 class InitializationException : public Exception
1026 {
1027 public:
1028 /**
1029 Constructor with an error message.
1030 \param msg Message to pass to the Exception.
1031 */
1032 InitializationException(const char* msg) : Exception(msg) {}
1033 };
1034
1035 /*
1036 Call method returning array: implementation
1037 */
1038 template <typename T>
1039 inline jni::Array<T> Object::callMethod(method_t method, internal::value_t* args,
1040 internal::ReturnTypeWrapper<jni::Array<T>> const&) const
1041 {
1042 jarray result = callMethod(method, args, internal::ReturnTypeWrapper<jarray>{});
1043 return jni::Array<T>(result, DeleteLocalInput);
1044 }
1045
1046 /*
1047 Array Implementation
1048 */
1049
1050 template <class TElement>
1051 Array<TElement>::Array() noexcept : Object(), _length(0)
1052 {
1053 }
1054
1055 template <class TElement>
1056 Array<TElement>::Array(jarray ref, int scopeFlags) : Object((jobject) ref, scopeFlags), _length(-1)
1057 {
1058 }
1059
1060 template <class TElement>
1061 Array<TElement>::Array(const Array<TElement>& other) : Object(other), _length(other._length)
1062 {
1063 }
1064
1065 template <class TElement>
1066 Array<TElement>::Array(Array<TElement>&& other) noexcept : Object((Object&&)other), _length(other._length)
1067 {
1068 other._length = 0;
1069 }
1070
1071 template <class TElement>
1072 Array<TElement>& Array<TElement>::operator=(const Array<TElement>& other)
1073 {
1074 if (&other != this)
1075 {
1076 Object::operator=(other);
1077 _length = other._length;
1078 }
1079
1080 return *this;
1081 }
1082
1083 template <class TElement>
1084 Array<TElement>& Array<TElement>::operator=(Array<TElement>&& other)
1085 {
1086 if (&other != this)
1087 {
1088 Object::operator=((Object&&) other);
1089 _length = other._length;
1090
1091 other._length = 0;
1092 }
1093
1094 return *this;
1095 }
1096
1097 template <class TElement>
1098 long Array<TElement>::getLength() const
1099 {
1100 if (_length < 0)
1101 {
1102 _length = internal::getArrayLength(getHandle());
1103 }
1104
1105 return _length;
1106 }
1107}
1108
1109#endif // _JNIPP_H_
1110