The open source OpenXR runtime
at main 1110 lines 43 kB view raw
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