The open source OpenXR runtime

external: Import jnipp

+4069
+7
src/external/CMakeLists.txt
··· 25 25 add_library(xrt-external-hungarian INTERFACE) 26 26 target_include_directories(xrt-external-hungarian INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/hungarian) 27 27 28 + # JNIPP 29 + if(ANDROID) 30 + add_library(xrt-external-jnipp STATIC 31 + jnipp/jnipp.cpp) 32 + target_include_directories(xrt-external-jnipp PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/jnipp) 33 + endif() 34 + 28 35 # OpenXR 29 36 add_library(xrt-external-openxr INTERFACE) 30 37 target_include_directories(xrt-external-openxr INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/openxr_includes)
+258
src/external/jnipp/.gitignore
··· 1 + ## Ignore Visual Studio temporary files, build results, and 2 + ## files generated by popular Visual Studio add-ons. 3 + 4 + # User-specific files 5 + *.suo 6 + *.user 7 + *.userosscache 8 + *.sln.docstates 9 + 10 + # User-specific files (MonoDevelop/Xamarin Studio) 11 + *.userprefs 12 + 13 + # Build results 14 + [Dd]ebug/ 15 + [Dd]ebugPublic/ 16 + [Rr]elease/ 17 + [Rr]eleases/ 18 + x64/ 19 + x86/ 20 + bld/ 21 + [Bb]in/ 22 + [Oo]bj/ 23 + [Ll]og/ 24 + 25 + # Visual Studio 2015 cache/options directory 26 + .vs/ 27 + # Uncomment if you have tasks that create the project's static files in wwwroot 28 + #wwwroot/ 29 + 30 + # MSTest test Results 31 + [Tt]est[Rr]esult*/ 32 + [Bb]uild[Ll]og.* 33 + 34 + # NUNIT 35 + *.VisualState.xml 36 + TestResult.xml 37 + 38 + # Build Results of an ATL Project 39 + [Dd]ebugPS/ 40 + [Rr]eleasePS/ 41 + dlldata.c 42 + 43 + # DNX 44 + project.lock.json 45 + artifacts/ 46 + 47 + *_i.c 48 + *_p.c 49 + *_i.h 50 + *.ilk 51 + *.meta 52 + *.obj 53 + *.pch 54 + *.pdb 55 + *.pgc 56 + *.pgd 57 + *.rsp 58 + *.sbr 59 + *.tlb 60 + *.tli 61 + *.tlh 62 + *.tmp 63 + *.tmp_proj 64 + *.log 65 + *.vspscc 66 + *.vssscc 67 + .builds 68 + *.pidb 69 + *.svclog 70 + *.scc 71 + 72 + # Chutzpah Test files 73 + _Chutzpah* 74 + 75 + # Visual C++ cache files 76 + ipch/ 77 + *.aps 78 + *.ncb 79 + *.opendb 80 + *.opensdf 81 + *.sdf 82 + *.cachefile 83 + *.VC.db 84 + *.VC.VC.opendb 85 + 86 + # Visual Studio profiler 87 + *.psess 88 + *.vsp 89 + *.vspx 90 + *.sap 91 + 92 + # TFS 2012 Local Workspace 93 + $tf/ 94 + 95 + # Guidance Automation Toolkit 96 + *.gpState 97 + 98 + # ReSharper is a .NET coding add-in 99 + _ReSharper*/ 100 + *.[Rr]e[Ss]harper 101 + *.DotSettings.user 102 + 103 + # JustCode is a .NET coding add-in 104 + .JustCode 105 + 106 + # TeamCity is a build add-in 107 + _TeamCity* 108 + 109 + # DotCover is a Code Coverage Tool 110 + *.dotCover 111 + 112 + # NCrunch 113 + _NCrunch_* 114 + .*crunch*.local.xml 115 + nCrunchTemp_* 116 + 117 + # MightyMoose 118 + *.mm.* 119 + AutoTest.Net/ 120 + 121 + # Web workbench (sass) 122 + .sass-cache/ 123 + 124 + # Installshield output folder 125 + [Ee]xpress/ 126 + 127 + # DocProject is a documentation generator add-in 128 + DocProject/buildhelp/ 129 + DocProject/Help/*.HxT 130 + DocProject/Help/*.HxC 131 + DocProject/Help/*.hhc 132 + DocProject/Help/*.hhk 133 + DocProject/Help/*.hhp 134 + DocProject/Help/Html2 135 + DocProject/Help/html 136 + 137 + # Click-Once directory 138 + publish/ 139 + 140 + # Publish Web Output 141 + *.[Pp]ublish.xml 142 + *.azurePubxml 143 + # TODO: Comment the next line if you want to checkin your web deploy settings 144 + # but database connection strings (with potential passwords) will be unencrypted 145 + *.pubxml 146 + *.publishproj 147 + 148 + # Microsoft Azure Web App publish settings. Comment the next line if you want to 149 + # checkin your Azure Web App publish settings, but sensitive information contained 150 + # in these scripts will be unencrypted 151 + PublishScripts/ 152 + 153 + # NuGet Packages 154 + *.nupkg 155 + # The packages folder can be ignored because of Package Restore 156 + **/packages/* 157 + # except build/, which is used as an MSBuild target. 158 + !**/packages/build/ 159 + # Uncomment if necessary however generally it will be regenerated when needed 160 + #!**/packages/repositories.config 161 + # NuGet v3's project.json files produces more ignoreable files 162 + *.nuget.props 163 + *.nuget.targets 164 + 165 + # Microsoft Azure Build Output 166 + csx/ 167 + *.build.csdef 168 + 169 + # Microsoft Azure Emulator 170 + ecf/ 171 + rcf/ 172 + 173 + # Windows Store app package directories and files 174 + AppPackages/ 175 + BundleArtifacts/ 176 + Package.StoreAssociation.xml 177 + _pkginfo.txt 178 + 179 + # Visual Studio cache files 180 + # files ending in .cache can be ignored 181 + *.[Cc]ache 182 + # but keep track of directories ending in .cache 183 + !*.[Cc]ache/ 184 + 185 + # Others 186 + ClientBin/ 187 + ~$* 188 + *~ 189 + *.dbmdl 190 + *.dbproj.schemaview 191 + *.pfx 192 + *.publishsettings 193 + node_modules/ 194 + orleans.codegen.cs 195 + 196 + # Since there are multiple workflows, uncomment next line to ignore bower_components 197 + # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 198 + #bower_components/ 199 + 200 + # RIA/Silverlight projects 201 + Generated_Code/ 202 + 203 + # Backup & report files from converting an old project file 204 + # to a newer Visual Studio version. Backup files are not needed, 205 + # because we have git ;-) 206 + _UpgradeReport_Files/ 207 + Backup*/ 208 + UpgradeLog*.XML 209 + UpgradeLog*.htm 210 + 211 + # SQL Server files 212 + *.mdf 213 + *.ldf 214 + 215 + # Business Intelligence projects 216 + *.rdl.data 217 + *.bim.layout 218 + *.bim_*.settings 219 + 220 + # Microsoft Fakes 221 + FakesAssemblies/ 222 + 223 + # GhostDoc plugin setting file 224 + *.GhostDoc.xml 225 + 226 + # Node.js Tools for Visual Studio 227 + .ntvs_analysis.dat 228 + 229 + # Visual Studio 6 build log 230 + *.plg 231 + 232 + # Visual Studio 6 workspace options file 233 + *.opt 234 + 235 + # Visual Studio LightSwitch build output 236 + **/*.HTMLClient/GeneratedArtifacts 237 + **/*.DesktopClient/GeneratedArtifacts 238 + **/*.DesktopClient/ModelManifest.xml 239 + **/*.Server/GeneratedArtifacts 240 + **/*.Server/ModelManifest.xml 241 + _Pvt_Extensions 242 + 243 + # Paket dependency manager 244 + .paket/paket.exe 245 + paket-files/ 246 + 247 + # FAKE - F# Make 248 + .fake/ 249 + 250 + # JetBrains Rider 251 + .idea/ 252 + *.sln.iml 253 + *.out 254 + *.o 255 + /test 256 + 257 + # Gradle 258 + .gradle/
+23
src/external/jnipp/Android.bp
··· 1 + 2 + cc_library_headers { 3 + name: "libjnipp-headers", 4 + export_include_dirs: ["."], 5 + vendor_available: true, 6 + } 7 + 8 + cc_library_static { 9 + name: "libjnipp", 10 + 11 + srcs: [ 12 + "jnipp.cpp", 13 + ], 14 + 15 + cppflags: [ "-fexceptions" ], 16 + header_libs: [ 17 + "libjnipp-headers", 18 + ], 19 + export_header_lib_headers: [ 20 + "libjnipp-headers" 21 + ], 22 + vendor_available: true, 23 + }
+21
src/external/jnipp/LICENSE
··· 1 + MIT License 2 + 3 + Copyright (c) 2016 Mitchell Dowd 4 + 5 + Permission is hereby granted, free of charge, to any person obtaining a copy 6 + of this software and associated documentation files (the "Software"), to deal 7 + in the Software without restriction, including without limitation the rights 8 + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 + copies of the Software, and to permit persons to whom the Software is 10 + furnished to do so, subject to the following conditions: 11 + 12 + The above copyright notice and this permission notice shall be included in all 13 + copies or substantial portions of the Software. 14 + 15 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 + SOFTWARE.
+107
src/external/jnipp/README.md
··· 1 + # Java Native Interface for C++ 2 + 3 + ## Overview 4 + 5 + JNIPP is just a C++ wrapper for the standard Java Native Interface (JNI). It 6 + tries to take some of the long-winded annoyance out of integrating your Java 7 + and C++ code. 8 + 9 + While this project has so far just been a utility library for my own usage, 10 + it seems to have caught the eye of some others who have also been looking for 11 + a suitable C++ JNI layer. If you have feature requests, do not hesitate to 12 + submit them as Github issues. Please be descriptive in your feature request. 13 + The more useful information you provide - along with justification on why it 14 + should be implemented - the more likely it is that I will add your feature. 15 + 16 + ## Requirements 17 + 18 + To compile you will need: 19 + 20 + - A C++11 compatible compiler 21 + - An installation of the Java Development Kit (JDK) 22 + - The `JAVA_HOME` environment variable, directed to your JDK installation. 23 + 24 + ## Usage 25 + 26 + > For comprehensive examples on how to use *jnipp*, see the `tests` project 27 + > in the project source code. 28 + 29 + There are two situations where the Java Native Interface would be needed. 30 + 31 + - A Java application calling C/C++ functions; or 32 + - A C/C++ application calling Java methods 33 + 34 + ### Calling Java from C++ 35 + 36 + The following is an example of calling Java from C++. 37 + 38 + ```C++ 39 + #include <jnipp.h> 40 + 41 + int main() 42 + { 43 + // An instance of the Java VM needs to be created. 44 + jni::Vm vm; 45 + 46 + // Create an instance of java.lang.Integer 47 + jni::Class Integer = jni::Class("java/lang/Integer"); 48 + jni::Object i = Integer.newInstance("1000"); 49 + 50 + // Call the `toString` method on that integer 51 + std::string str = i.call<std::string>("toString"); 52 + 53 + // The Java VM is automatically destroyed when it goes out of scope. 54 + return 0; 55 + } 56 + ``` 57 + 58 + ### Calling C++ from Java 59 + 60 + Consider a basic Java program: 61 + 62 + ```Java 63 + package com.example; 64 + 65 + class Demo { 66 + public int value; 67 + 68 + public static void main(String[] args) { 69 + Demo demo = new Demo(); 70 + demo.value = 1000; 71 + demo.run(); 72 + } 73 + 74 + public native void run(); 75 + } 76 + ``` 77 + 78 + A matching C++ library which uses *jnipp* could look like: 79 + 80 + ```C++ 81 + #include <jnipp.h> 82 + #include <iostream> 83 + 84 + /* 85 + The signature here is defind by the JNI standard, so must be adhered to. 86 + Although, to prevent pollution of the global namespace, the JNIEnv and 87 + jobject types defind by the standard JNI have been placed into the 88 + jni namespace. 89 + */ 90 + extern "C" void Java_com_example_Demo_run(jni::JNIEnv* env, jni::jobject obj) 91 + { 92 + // jnipp only needs initialising once, but it doesn't hurt to do it again. 93 + jni::init(env); 94 + 95 + // Capture the supplied object. 96 + jni::Object demo(obj); 97 + 98 + // Print the contents of the `value` field to stdout. 99 + std::cout << demo.get<int>("value") << std::endl; 100 + } 101 + ``` 102 + 103 + ## Configuration 104 + 105 + By default, *jnipp* uses std::runtime_error as the base exception class. If you wish, 106 + you can define `JNIPP_EXCEPTION_CLASS` to be the exception class you wish to use, before 107 + including `jnipp.h`. It just needs a `const char*` constructor.
+8
src/external/jnipp/android/AndroidManifest.xml
··· 1 + <?xml version="1.0" encoding="utf-8"?> 2 + <!-- BEGIN_INCLUDE(manifest) --> 3 + <manifest xmlns:android="http://schemas.android.com/apk/res/android" 4 + package="jnipp" 5 + android:versionCode="1" 6 + android:versionName="1.0"> 7 + </manifest> 8 + <!-- END_INCLUDE(manifest) -->
+12
src/external/jnipp/android/CMakeLists.txt
··· 1 + CMAKE_MINIMUM_REQUIRED(VERSION 3.4.1) 2 + 3 + GET_FILENAME_COMPONENT(root_dir "../.." ABSOLUTE) 4 + 5 + LINK_DIRECTORIES("${root_dir}/${ANDROID_ABI}") 6 + 7 + SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${root_dir}/${ANDROID_ABI}") 8 + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DANDROID_STL=c++_static -std=gnu++11 -fexceptions") 9 + 10 + FILE(GLOB sources ../*.cpp ../common/*.cpp ../android/*.cpp) 11 + 12 + ADD_LIBRARY(jnipp SHARED ${sources})
+30
src/external/jnipp/build.gradle
··· 1 + apply plugin: 'com.android.library' 2 + 3 + android { 4 + compileSdkVersion 26 5 + buildToolsVersion '28.0.3' 6 + 7 + defaultConfig { 8 + minSdkVersion 15 9 + targetSdkVersion 26 10 + } 11 + 12 + buildTypes { 13 + release { 14 + minifyEnabled = false 15 + proguardFiles getDefaultProguardFile('proguard-android.txt') 16 + } 17 + } 18 + 19 + sourceSets { 20 + main { 21 + manifest.srcFile 'android/AndroidManifest.xml' 22 + } 23 + } 24 + 25 + externalNativeBuild { 26 + cmake { 27 + path 'android/CMakeLists.txt' 28 + } 29 + } 30 + }
+10
src/external/jnipp/dotest.sh
··· 1 + #!/bin/sh 2 + set -e 3 + ( 4 + cd $(dirname $0) 5 + export JAVA_HOME=/home/ryan/apps/android-studio/jre/ 6 + make "$@" 7 + if [ -x ./test ]; then 8 + ./test 9 + fi 10 + )
+1531
src/external/jnipp/jnipp.cpp
··· 1 + #ifdef _WIN32 2 + # define WIN32_LEAN_AND_MEAN 1 3 + 4 + // Windows Dependencies 5 + # include <windows.h> 6 + #else 7 + // UNIX Dependencies 8 + # include <dlfcn.h> 9 + #endif 10 + 11 + // External Dependencies 12 + #include <jni.h> 13 + 14 + // Standard Dependencies 15 + #include <atomic> 16 + #include <string> 17 + 18 + // Local Dependencies 19 + #include "jnipp.h" 20 + 21 + namespace jni 22 + { 23 + // Static Variables 24 + static std::atomic_bool isVm(false); 25 + static JavaVM* javaVm = nullptr; 26 + 27 + /** 28 + Maintains the lifecycle of a JNIEnv. 29 + */ 30 + class ScopedEnv final 31 + { 32 + public: 33 + ScopedEnv() noexcept : _vm(nullptr), _env(nullptr), _attached(false) {} 34 + ~ScopedEnv(); 35 + 36 + void init(JavaVM* vm); 37 + JNIEnv* get() const noexcept { return _env; } 38 + 39 + private: 40 + // Instance Variables 41 + JavaVM* _vm; 42 + JNIEnv* _env; 43 + bool _attached; ///< Manually attached, as opposed to already attached. 44 + }; 45 + 46 + ScopedEnv::~ScopedEnv() 47 + { 48 + if (_vm && _attached) 49 + _vm->DetachCurrentThread(); 50 + } 51 + 52 + void ScopedEnv::init(JavaVM* vm) 53 + { 54 + if (_env != nullptr) 55 + return; 56 + 57 + if (vm == nullptr) 58 + throw InitializationException("JNI not initialized"); 59 + 60 + if (vm->GetEnv((void**)&_env, JNI_VERSION_1_2) != JNI_OK) 61 + { 62 + #ifdef __ANDROID__ 63 + if (vm->AttachCurrentThread(&_env, nullptr) != 0) 64 + #else 65 + if (vm->AttachCurrentThread((void**)&_env, nullptr) != 0) 66 + #endif 67 + throw InitializationException("Could not attach JNI to thread"); 68 + 69 + _attached = true; 70 + } 71 + 72 + _vm = vm; 73 + } 74 + 75 + /* 76 + Helper Functions 77 + */ 78 + 79 + #ifdef _WIN32 80 + 81 + static bool fileExists(const std::string& filePath) 82 + { 83 + DWORD attr = ::GetFileAttributesA(filePath.c_str()); 84 + 85 + return attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY); 86 + } 87 + 88 + #else 89 + 90 + /** 91 + Convert from a UTF-16 Java string to a UTF-32 string. 92 + */ 93 + std::wstring toWString(const jchar* str, jsize length) 94 + { 95 + std::wstring result; 96 + 97 + result.reserve(length); 98 + 99 + for (jsize i = 0; i < length; ++i) 100 + { 101 + wchar_t ch = str[i]; 102 + 103 + // Check for a two-segment character. 104 + if (ch >= wchar_t(0xD800) && ch <= wchar_t(0xDBFF)) { 105 + if (i + 1 >= length) 106 + break; 107 + 108 + // Create a single, 32-bit character. 109 + ch = (ch - wchar_t(0xD800)) << 10; 110 + ch += str[i++] - wchar_t(0x1DC00); 111 + } 112 + 113 + result += ch; 114 + } 115 + 116 + return result; 117 + } 118 + 119 + /** 120 + Convert from a UTF-32 string to a UTF-16 Java string. 121 + */ 122 + std::basic_string<jchar> toJString(const wchar_t* str, size_t length) 123 + { 124 + std::basic_string<jchar> result; 125 + 126 + result.reserve(length * 2); // Worst case scenario. 127 + 128 + for (size_t i = 0; i < length; ++i) 129 + { 130 + wchar_t ch = str[i]; 131 + 132 + // Check for multi-byte UTF-16 character. 133 + if (ch > wchar_t(0xFFFF)) { 134 + ch -= uint32_t(0x10000); 135 + 136 + // Add the first of the two-segment character. 137 + result += jchar(0xD800 + (ch >> 10)); 138 + ch = wchar_t(0xDC00) + (ch & 0x03FF); 139 + } 140 + 141 + result += jchar(ch); 142 + } 143 + 144 + return result; 145 + } 146 + 147 + #endif // _WIN32 148 + 149 + JNIEnv* env() 150 + { 151 + static thread_local ScopedEnv env; 152 + 153 + if (env.get() == nullptr) 154 + env.init(javaVm); 155 + 156 + return env.get(); 157 + } 158 + 159 + static jclass findClass(const char* name) 160 + { 161 + jclass ref = env()->FindClass(name); 162 + 163 + if (ref == nullptr) 164 + { 165 + env()->ExceptionClear(); 166 + throw NameResolutionException(name); 167 + } 168 + 169 + return ref; 170 + } 171 + 172 + static void handleJavaExceptions() 173 + { 174 + JNIEnv* env = jni::env(); 175 + 176 + jthrowable exception = env->ExceptionOccurred(); 177 + 178 + if (exception != nullptr) 179 + { 180 + Object obj(exception, Object::Temporary); 181 + 182 + env->ExceptionClear(); 183 + std::string msg = obj.call<std::string>("toString"); 184 + throw InvocationException(msg.c_str()); 185 + } 186 + } 187 + 188 + static std::string toString(jobject handle, bool deleteLocal = true) 189 + { 190 + std::string result; 191 + 192 + if (handle != nullptr) 193 + { 194 + JNIEnv* env = jni::env(); 195 + 196 + const char* chars = env->GetStringUTFChars(jstring(handle), nullptr); 197 + result.assign(chars, env->GetStringUTFLength(jstring(handle))); 198 + env->ReleaseStringUTFChars(jstring(handle), chars); 199 + 200 + if (deleteLocal) 201 + env->DeleteLocalRef(handle); 202 + } 203 + 204 + return result; 205 + } 206 + 207 + static std::wstring toWString(jobject handle, bool deleteLocal = true) 208 + { 209 + std::wstring result; 210 + 211 + if (handle != nullptr) 212 + { 213 + JNIEnv* env = jni::env(); 214 + 215 + const jchar* chars = env->GetStringChars(jstring(handle), nullptr); 216 + #ifdef _WIN32 217 + result.assign((const wchar_t*) chars, env->GetStringLength(jstring(handle))); 218 + #else 219 + result = toWString(chars, env->GetStringLength(jstring(handle))); 220 + #endif 221 + env->ReleaseStringChars(jstring(handle), chars); 222 + 223 + if (deleteLocal) 224 + env->DeleteLocalRef(handle); 225 + } 226 + 227 + return result; 228 + } 229 + 230 + 231 + /* 232 + Stand-alone Function Implementations 233 + */ 234 + 235 + void init(JNIEnv* env) 236 + { 237 + bool expected = false; 238 + 239 + if (isVm.compare_exchange_strong(expected, true)) 240 + { 241 + if (javaVm == nullptr && env->GetJavaVM(&javaVm) != 0) 242 + throw InitializationException("Could not acquire Java VM"); 243 + } 244 + } 245 + 246 + void init(JavaVM* vm) { 247 + bool expected = false; 248 + 249 + if (isVm.compare_exchange_strong(expected, true)) 250 + { 251 + javaVm = vm; 252 + } 253 + } 254 + /* 255 + Object Implementation 256 + */ 257 + 258 + Object::Object() noexcept : _handle(nullptr), _class(nullptr), _isGlobal(false) 259 + { 260 + } 261 + 262 + Object::Object(const Object& other) : _handle(nullptr), _class(nullptr), _isGlobal(!other.isNull()) 263 + { 264 + if (!other.isNull()) 265 + _handle = env()->NewGlobalRef(other._handle); 266 + } 267 + 268 + Object::Object(Object&& other) noexcept : _handle(other._handle), _class(other._class), _isGlobal(other._isGlobal) 269 + { 270 + other._handle = nullptr; 271 + other._class = nullptr; 272 + other._isGlobal = false; 273 + } 274 + 275 + Object::Object(jobject ref, int scopeFlags) : _handle(ref), _class(nullptr), _isGlobal((scopeFlags & Temporary) == 0) 276 + { 277 + if (!_isGlobal) 278 + return; 279 + 280 + JNIEnv* env = jni::env(); 281 + 282 + _handle = env->NewGlobalRef(ref); 283 + 284 + if (scopeFlags & DeleteLocalInput) 285 + env->DeleteLocalRef(ref); 286 + } 287 + 288 + Object::~Object() noexcept 289 + { 290 + JNIEnv* env = jni::env(); 291 + 292 + if (_isGlobal) 293 + env->DeleteGlobalRef(_handle); 294 + 295 + if (_class != nullptr) 296 + env->DeleteGlobalRef(_class); 297 + } 298 + 299 + Object& Object::operator=(const Object& other) 300 + { 301 + if (_handle != other._handle) 302 + { 303 + JNIEnv* env = jni::env(); 304 + 305 + // Ditch the old reference. 306 + if (_isGlobal) 307 + env->DeleteGlobalRef(_handle); 308 + if (_class != nullptr) 309 + env->DeleteGlobalRef(_class); 310 + 311 + // Assign the new reference. 312 + if ((_isGlobal = !other.isNull()) != false) 313 + _handle = env->NewGlobalRef(other._handle); 314 + 315 + _class = nullptr; 316 + } 317 + 318 + return *this; 319 + } 320 + 321 + bool Object::operator==(const Object& other) const 322 + { 323 + return env()->IsSameObject(_handle, other._handle) != JNI_FALSE; 324 + } 325 + 326 + Object& Object::operator=(Object&& other) 327 + { 328 + if (_handle != other._handle) 329 + { 330 + JNIEnv* env = jni::env(); 331 + 332 + // Ditch the old reference. 333 + if (_isGlobal) 334 + env->DeleteGlobalRef(_handle); 335 + if (_class != nullptr) 336 + env->DeleteGlobalRef(_class); 337 + 338 + // Assign the new reference. 339 + _handle = other._handle; 340 + _isGlobal = other._isGlobal; 341 + _class = other._class; 342 + 343 + other._handle = nullptr; 344 + other._isGlobal = false; 345 + other._class = nullptr; 346 + } 347 + 348 + return *this; 349 + } 350 + 351 + bool Object::isNull() const noexcept 352 + { 353 + return _handle == nullptr || env()->IsSameObject(_handle, nullptr); 354 + } 355 + 356 + template <> void Object::callMethod(method_t method, internal::value_t* args) const 357 + { 358 + env()->CallVoidMethodA(_handle, method, (jvalue*) args); 359 + handleJavaExceptions(); 360 + } 361 + 362 + template <> bool Object::callMethod(method_t method, internal::value_t* args) const 363 + { 364 + auto result = env()->CallBooleanMethodA(_handle, method, (jvalue*) args); 365 + handleJavaExceptions(); 366 + return result != 0; 367 + } 368 + 369 + template <> bool Object::get(field_t field) const 370 + { 371 + return env()->GetBooleanField(_handle, field) != 0; 372 + } 373 + 374 + template <> void Object::set(field_t field, const bool& value) 375 + { 376 + env()->SetBooleanField(_handle, field, value); 377 + } 378 + 379 + template <> byte_t Object::callMethod(method_t method, internal::value_t* args) const 380 + { 381 + auto result = env()->CallByteMethodA(_handle, method, (jvalue*) args); 382 + handleJavaExceptions(); 383 + return result; 384 + } 385 + 386 + template <> wchar_t Object::callMethod(method_t method, internal::value_t* args) const 387 + { 388 + auto result = env()->CallCharMethodA(_handle, method, (jvalue*) args); 389 + handleJavaExceptions(); 390 + return result; 391 + } 392 + 393 + template <> short Object::callMethod(method_t method, internal::value_t* args) const 394 + { 395 + auto result = env()->CallShortMethodA(_handle, method, (jvalue*) args); 396 + handleJavaExceptions(); 397 + return result; 398 + } 399 + 400 + template <> int Object::callMethod(method_t method, internal::value_t* args) const 401 + { 402 + auto result = env()->CallIntMethodA(_handle, method, (jvalue*) args); 403 + handleJavaExceptions(); 404 + return result; 405 + } 406 + 407 + template <> long long Object::callMethod(method_t method, internal::value_t* args) const 408 + { 409 + auto result = env()->CallLongMethodA(_handle, method, (jvalue*) args); 410 + handleJavaExceptions(); 411 + return result; 412 + } 413 + 414 + template <> float Object::callMethod(method_t method, internal::value_t* args) const 415 + { 416 + auto result = env()->CallFloatMethodA(_handle, method, (jvalue*) args); 417 + handleJavaExceptions(); 418 + return result; 419 + } 420 + 421 + template <> double Object::callMethod(method_t method, internal::value_t* args) const 422 + { 423 + auto result = env()->CallDoubleMethodA(_handle, method, (jvalue*) args); 424 + handleJavaExceptions(); 425 + return result; 426 + } 427 + 428 + template <> std::string Object::callMethod(method_t method, internal::value_t* args) const 429 + { 430 + auto result = env()->CallObjectMethodA(_handle, method, (jvalue*) args); 431 + handleJavaExceptions(); 432 + return toString(result); 433 + } 434 + 435 + template <> std::wstring Object::callMethod(method_t method, internal::value_t* args) const 436 + { 437 + auto result = env()->CallObjectMethodA(_handle, method, (jvalue*) args); 438 + handleJavaExceptions(); 439 + return toWString(result); 440 + } 441 + 442 + template <> jni::Object Object::callMethod(method_t method, internal::value_t* args) const 443 + { 444 + auto result = env()->CallObjectMethodA(_handle, method, (jvalue*) args); 445 + handleJavaExceptions(); 446 + return Object(result, DeleteLocalInput); 447 + } 448 + 449 + template <> byte_t Object::get(field_t field) const 450 + { 451 + return env()->GetByteField(_handle, field); 452 + } 453 + 454 + template <> wchar_t Object::get(field_t field) const 455 + { 456 + return env()->GetCharField(_handle, field); 457 + } 458 + 459 + template <> short Object::get(field_t field) const 460 + { 461 + return env()->GetShortField(_handle, field); 462 + } 463 + 464 + template <> int Object::get(field_t field) const 465 + { 466 + return env()->GetIntField(_handle, field); 467 + } 468 + 469 + template <> long long Object::get(field_t field) const 470 + { 471 + return env()->GetLongField(_handle, field); 472 + } 473 + 474 + template <> float Object::get(field_t field) const 475 + { 476 + return env()->GetFloatField(_handle, field); 477 + } 478 + 479 + template <> double Object::get(field_t field) const 480 + { 481 + return env()->GetDoubleField(_handle, field); 482 + } 483 + 484 + template <> std::string Object::get(field_t field) const 485 + { 486 + return toString(env()->GetObjectField(_handle, field)); 487 + } 488 + 489 + template <> std::wstring Object::get(field_t field) const 490 + { 491 + return toWString(env()->GetObjectField(_handle, field)); 492 + } 493 + 494 + template <> Object Object::get(field_t field) const 495 + { 496 + return Object(env()->GetObjectField(_handle, field), DeleteLocalInput); 497 + } 498 + 499 + template <> void Object::set(field_t field, const byte_t& value) 500 + { 501 + env()->SetByteField(_handle, field, value); 502 + } 503 + 504 + template <> void Object::set(field_t field, const wchar_t& value) 505 + { 506 + env()->SetCharField(_handle, field, value); 507 + } 508 + 509 + template <> void Object::set(field_t field, const short& value) 510 + { 511 + env()->SetShortField(_handle, field, value); 512 + } 513 + 514 + template <> void Object::set(field_t field, const int& value) 515 + { 516 + env()->SetIntField(_handle, field, value); 517 + } 518 + 519 + template <> void Object::set(field_t field, const long long& value) 520 + { 521 + env()->SetLongField(_handle, field, value); 522 + } 523 + 524 + template <> void Object::set(field_t field, const float& value) 525 + { 526 + env()->SetFloatField(_handle, field, value); 527 + } 528 + 529 + template <> void Object::set(field_t field, const double& value) 530 + { 531 + env()->SetDoubleField(_handle, field, value); 532 + } 533 + 534 + template <> void Object::set(field_t field, const std::string& value) 535 + { 536 + JNIEnv* env = jni::env(); 537 + 538 + jobject handle = env->NewStringUTF(value.c_str()); 539 + env->SetObjectField(_handle, field, handle); 540 + env->DeleteLocalRef(handle); 541 + } 542 + 543 + template <> void Object::set(field_t field, const std::wstring& value) 544 + { 545 + JNIEnv* env = jni::env(); 546 + 547 + #ifdef _WIN32 548 + jobject handle = env->NewString((const jchar*) value.c_str(), jsize(value.length())); 549 + #else 550 + auto jstr = toJString(value.c_str(), value.length()); 551 + jobject handle = env->NewString(jstr.c_str(), jsize(jstr.length())); 552 + #endif 553 + env->SetObjectField(_handle, field, handle); 554 + env->DeleteLocalRef(handle); 555 + } 556 + 557 + template <> void Object::set(field_t field, const wchar_t* const& value) 558 + { 559 + JNIEnv* env = jni::env(); 560 + #ifdef _WIN32 561 + jobject handle = env->NewString((const jchar*) value, jsize(std::wcslen(value))); 562 + #else 563 + auto jstr = toJString(value, std::wcslen(value)); 564 + jobject handle = env->NewString(jstr.c_str(), jsize(jstr.length())); 565 + #endif 566 + env->SetObjectField(_handle, field, handle); 567 + env->DeleteLocalRef(handle); 568 + } 569 + 570 + template <> void Object::set(field_t field, const char* const& value) 571 + { 572 + JNIEnv* env = jni::env(); 573 + 574 + jobject handle = env->NewStringUTF(value); 575 + env->SetObjectField(_handle, field, handle); 576 + env->DeleteLocalRef(handle); 577 + } 578 + 579 + template <> void Object::set(field_t field, const Object& value) 580 + { 581 + env()->SetObjectField(_handle, field, value.getHandle()); 582 + } 583 + 584 + template <> void Object::set(field_t field, const Object* const& value) 585 + { 586 + env()->SetObjectField(_handle, field, value ? value->getHandle() : nullptr); 587 + } 588 + 589 + jclass Object::getClass() const 590 + { 591 + if (_class == nullptr) 592 + { 593 + JNIEnv* env = jni::env(); 594 + 595 + jclass classRef = env->GetObjectClass(_handle); 596 + _class = jclass(env->NewGlobalRef(classRef)); 597 + env->DeleteLocalRef(classRef); 598 + } 599 + 600 + return _class; 601 + } 602 + 603 + method_t Object::getMethod(const char* name, const char* signature) const 604 + { 605 + return Class(getClass(), Temporary).getMethod(name, signature); 606 + } 607 + 608 + method_t Object::getMethod(const char* nameAndSignature) const 609 + { 610 + return Class(getClass(), Temporary).getMethod(nameAndSignature); 611 + } 612 + 613 + field_t Object::getField(const char* name, const char* signature) const 614 + { 615 + return Class(getClass(), Temporary).getField(name, signature); 616 + } 617 + 618 + jobject Object::makeLocalReference() const 619 + { 620 + if (isNull()) 621 + return nullptr; 622 + return env()->NewLocalRef(_handle); 623 + } 624 + 625 + /* 626 + Class Implementation 627 + */ 628 + 629 + Class::Class(const char* name) : Object(findClass(name), DeleteLocalInput) 630 + { 631 + } 632 + 633 + Class::Class(jclass ref, int scopeFlags) : Object(ref, scopeFlags) 634 + { 635 + } 636 + 637 + Object Class::newInstance() const 638 + { 639 + method_t constructor = getMethod("<init>", "()V"); 640 + jobject obj = env()->NewObject(getHandle(), constructor); 641 + 642 + handleJavaExceptions(); 643 + 644 + return Object(obj, Object::DeleteLocalInput); 645 + } 646 + 647 + field_t Class::getField(const char* name, const char* signature) const 648 + { 649 + jfieldID id = env()->GetFieldID(getHandle(), name, signature); 650 + 651 + if (id == nullptr) 652 + throw NameResolutionException(name); 653 + 654 + return id; 655 + } 656 + 657 + field_t Class::getStaticField(const char* name, const char* signature) const 658 + { 659 + jfieldID id = env()->GetStaticFieldID(getHandle(), name, signature); 660 + 661 + if (id == nullptr) 662 + throw NameResolutionException(name); 663 + 664 + return id; 665 + } 666 + 667 + method_t Class::getMethod(const char* name, const char* signature) const 668 + { 669 + jmethodID id = env()->GetMethodID(getHandle(), name, signature); 670 + 671 + if (id == nullptr) 672 + throw NameResolutionException(name); 673 + 674 + return id; 675 + } 676 + 677 + 678 + method_t Class::getMethod(const char* nameAndSignature) const 679 + { 680 + jmethodID id = nullptr; 681 + const char* sig = std::strchr(nameAndSignature, '('); 682 + 683 + if (sig != nullptr) 684 + return getMethod(std::string(nameAndSignature, sig - nameAndSignature).c_str(), sig); 685 + 686 + if (id == nullptr) 687 + throw NameResolutionException(nameAndSignature); 688 + 689 + return id; 690 + } 691 + 692 + method_t Class::getStaticMethod(const char* name, const char* signature) const 693 + { 694 + jmethodID id = env()->GetStaticMethodID(getHandle(), name, signature); 695 + 696 + if (id == nullptr) 697 + throw NameResolutionException(name); 698 + 699 + return id; 700 + } 701 + 702 + method_t Class::getStaticMethod(const char* nameAndSignature) const 703 + { 704 + jmethodID id = nullptr; 705 + const char* sig = std::strchr(nameAndSignature, '('); 706 + 707 + if (sig != nullptr) 708 + return getStaticMethod(std::string(nameAndSignature, sig - nameAndSignature).c_str(), sig); 709 + 710 + if (id == nullptr) 711 + throw NameResolutionException(nameAndSignature); 712 + 713 + return id; 714 + } 715 + 716 + Class Class::getParent() const 717 + { 718 + return Class(env()->GetSuperclass(getHandle()), DeleteLocalInput); 719 + } 720 + 721 + std::string Class::getName() const 722 + { 723 + return Object::call<std::string>("getName"); 724 + } 725 + 726 + template <> bool Class::get(field_t field) const 727 + { 728 + return env()->GetStaticBooleanField(getHandle(), field) != 0; 729 + } 730 + 731 + template <> byte_t Class::get(field_t field) const 732 + { 733 + return env()->GetStaticByteField(getHandle(), field); 734 + } 735 + 736 + template <> wchar_t Class::get(field_t field) const 737 + { 738 + return env()->GetStaticCharField(getHandle(), field); 739 + } 740 + 741 + template <> short Class::get(field_t field) const 742 + { 743 + return env()->GetStaticShortField(getHandle(), field); 744 + } 745 + 746 + template <> int Class::get(field_t field) const 747 + { 748 + return env()->GetStaticIntField(getHandle(), field); 749 + } 750 + 751 + template <> long long Class::get(field_t field) const 752 + { 753 + return env()->GetStaticLongField(getHandle(), field); 754 + } 755 + 756 + template <> float Class::get(field_t field) const 757 + { 758 + return env()->GetStaticFloatField(getHandle(), field); 759 + } 760 + 761 + template <> double Class::get(field_t field) const 762 + { 763 + return env()->GetStaticDoubleField(getHandle(), field); 764 + } 765 + 766 + template <> std::string Class::get(field_t field) const 767 + { 768 + return toString(env()->GetStaticObjectField(getHandle(), field)); 769 + } 770 + 771 + template <> std::wstring Class::get(field_t field) const 772 + { 773 + return toWString(env()->GetStaticObjectField(getHandle(), field)); 774 + } 775 + 776 + template <> Object Class::get(field_t field) const 777 + { 778 + return Object(env()->GetStaticObjectField(getHandle(), field), DeleteLocalInput); 779 + } 780 + 781 + template <> void Class::set(field_t field, const bool& value) 782 + { 783 + env()->SetStaticBooleanField(getHandle(), field, value); 784 + } 785 + 786 + template <> void Class::set(field_t field, const byte_t& value) 787 + { 788 + env()->SetStaticByteField(getHandle(), field, value); 789 + } 790 + 791 + template <> void Class::set(field_t field, const wchar_t& value) 792 + { 793 + env()->SetStaticCharField(getHandle(), field, value); 794 + } 795 + 796 + template <> void Class::set(field_t field, const short& value) 797 + { 798 + env()->SetStaticShortField(getHandle(), field, value); 799 + } 800 + 801 + template <> void Class::set(field_t field, const int& value) 802 + { 803 + env()->SetStaticIntField(getHandle(), field, value); 804 + } 805 + 806 + template <> void Class::set(field_t field, const long long& value) 807 + { 808 + env()->SetStaticLongField(getHandle(), field, value); 809 + } 810 + 811 + template <> void Class::set(field_t field, const float& value) 812 + { 813 + env()->SetStaticFloatField(getHandle(), field, value); 814 + } 815 + 816 + template <> void Class::set(field_t field, const double& value) 817 + { 818 + env()->SetStaticDoubleField(getHandle(), field, value); 819 + } 820 + 821 + template <> void Class::set(field_t field, const Object& value) 822 + { 823 + env()->SetStaticObjectField(getHandle(), field, value.getHandle()); 824 + } 825 + 826 + template <> void Class::set(field_t field, const Object* const& value) 827 + { 828 + env()->SetStaticObjectField(getHandle(), field, value ? value->getHandle() : nullptr); 829 + } 830 + 831 + template <> void Class::set(field_t field, const std::string& value) 832 + { 833 + JNIEnv* env = jni::env(); 834 + 835 + jobject handle = env->NewStringUTF(value.c_str()); 836 + env->SetStaticObjectField(getHandle(), field, handle); 837 + env->DeleteLocalRef(handle); 838 + } 839 + 840 + template <> void Class::set(field_t field, const std::wstring& value) 841 + { 842 + JNIEnv* env = jni::env(); 843 + 844 + #ifdef _WIN32 845 + jobject handle = env->NewString((const jchar*) value.c_str(), jsize(value.length())); 846 + #else 847 + auto jstr = toJString(value.c_str(), value.length()); 848 + jobject handle = env->NewString(jstr.c_str(), jsize(jstr.length())); 849 + #endif 850 + env->SetStaticObjectField(getHandle(), field, handle); 851 + env->DeleteLocalRef(handle); 852 + } 853 + 854 + template <> void Class::callStaticMethod(method_t method, internal::value_t* args) const 855 + { 856 + env()->CallStaticVoidMethodA(getHandle(), method, (jvalue*) args); 857 + handleJavaExceptions(); 858 + } 859 + 860 + template <> bool Class::callStaticMethod(method_t method, internal::value_t* args) const 861 + { 862 + auto result = env()->CallStaticBooleanMethodA(getHandle(), method, (jvalue*) args); 863 + handleJavaExceptions(); 864 + return result != 0; 865 + } 866 + 867 + template <> byte_t Class::callStaticMethod(method_t method, internal::value_t* args) const 868 + { 869 + auto result = env()->CallStaticByteMethodA(getHandle(), method, (jvalue*) args); 870 + handleJavaExceptions(); 871 + return result; 872 + } 873 + 874 + template <> wchar_t Class::callStaticMethod(method_t method, internal::value_t* args) const 875 + { 876 + auto result = env()->CallStaticCharMethodA(getHandle(), method, (jvalue*) args); 877 + handleJavaExceptions(); 878 + return result; 879 + } 880 + 881 + template <> short Class::callStaticMethod(method_t method, internal::value_t* args) const 882 + { 883 + auto result = env()->CallStaticShortMethodA(getHandle(), method, (jvalue*) args); 884 + handleJavaExceptions(); 885 + return result; 886 + } 887 + 888 + template <> int Class::callStaticMethod(method_t method, internal::value_t* args) const 889 + { 890 + auto result = env()->CallStaticIntMethodA(getHandle(), method, (jvalue*) args); 891 + handleJavaExceptions(); 892 + return result; 893 + } 894 + 895 + template <> long long Class::callStaticMethod(method_t method, internal::value_t* args) const 896 + { 897 + auto result = env()->CallStaticLongMethodA(getHandle(), method, (jvalue*) args); 898 + handleJavaExceptions(); 899 + return result; 900 + } 901 + 902 + template <> float Class::callStaticMethod(method_t method, internal::value_t* args) const 903 + { 904 + auto result = env()->CallStaticFloatMethodA(getHandle(), method, (jvalue*) args); 905 + handleJavaExceptions(); 906 + return result; 907 + } 908 + 909 + template <> double Class::callStaticMethod(method_t method, internal::value_t* args) const 910 + { 911 + auto result = env()->CallStaticDoubleMethodA(getHandle(), method, (jvalue*) args); 912 + handleJavaExceptions(); 913 + return result; 914 + } 915 + 916 + template <> std::string Class::callStaticMethod(method_t method, internal::value_t* args) const 917 + { 918 + auto result = env()->CallStaticObjectMethodA(getHandle(), method, (jvalue*) args); 919 + handleJavaExceptions(); 920 + return toString(result); 921 + } 922 + 923 + template <> std::wstring Class::callStaticMethod(method_t method, internal::value_t* args) const 924 + { 925 + auto result = env()->CallStaticObjectMethodA(getHandle(), method, (jvalue*) args); 926 + handleJavaExceptions(); 927 + return toWString(result); 928 + } 929 + 930 + template <> jni::Object Class::callStaticMethod(method_t method, internal::value_t* args) const 931 + { 932 + auto result = env()->CallStaticObjectMethodA(getHandle(), method, (jvalue*) args); 933 + handleJavaExceptions(); 934 + return Object(result, DeleteLocalInput); 935 + } 936 + 937 + template <> void Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 938 + { 939 + env()->CallNonvirtualVoidMethodA(obj, getHandle(), method, (jvalue*) args); 940 + handleJavaExceptions(); 941 + } 942 + 943 + template <> bool Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 944 + { 945 + auto result = env()->CallNonvirtualBooleanMethodA(obj, getHandle(), method, (jvalue*) args); 946 + handleJavaExceptions(); 947 + return result != 0; 948 + } 949 + 950 + template <> byte_t Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 951 + { 952 + auto result = env()->CallNonvirtualByteMethodA(obj, getHandle(), method, (jvalue*) args); 953 + handleJavaExceptions(); 954 + return result; 955 + } 956 + 957 + template <> wchar_t Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 958 + { 959 + auto result = env()->CallNonvirtualCharMethodA(obj, getHandle(), method, (jvalue*) args); 960 + handleJavaExceptions(); 961 + return result; 962 + } 963 + 964 + template <> short Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 965 + { 966 + auto result = env()->CallNonvirtualShortMethodA(obj, getHandle(), method, (jvalue*) args); 967 + handleJavaExceptions(); 968 + return result; 969 + } 970 + 971 + template <> int Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 972 + { 973 + auto result = env()->CallNonvirtualIntMethodA(obj, getHandle(), method, (jvalue*) args); 974 + handleJavaExceptions(); 975 + return result; 976 + } 977 + 978 + template <> long long Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 979 + { 980 + auto result = env()->CallNonvirtualLongMethodA(obj, getHandle(), method, (jvalue*) args); 981 + handleJavaExceptions(); 982 + return result; 983 + } 984 + 985 + template <> float Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 986 + { 987 + auto result = env()->CallNonvirtualFloatMethodA(obj, getHandle(), method, (jvalue*) args); 988 + handleJavaExceptions(); 989 + return result; 990 + } 991 + 992 + template <> double Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 993 + { 994 + auto result = env()->CallNonvirtualDoubleMethodA(obj, getHandle(), method, (jvalue*) args); 995 + handleJavaExceptions(); 996 + return result; 997 + } 998 + 999 + template <> std::string Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 1000 + { 1001 + auto result = env()->CallNonvirtualObjectMethodA(obj, getHandle(), method, (jvalue*)args); 1002 + handleJavaExceptions(); 1003 + return toString(result); 1004 + } 1005 + 1006 + template <> std::wstring Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 1007 + { 1008 + auto result = env()->CallNonvirtualObjectMethodA(obj, getHandle(), method, (jvalue*)args); 1009 + handleJavaExceptions(); 1010 + return toWString(result); 1011 + } 1012 + 1013 + template <> Object Class::callExactMethod(jobject obj, method_t method, internal::value_t* args) const 1014 + { 1015 + auto result = env()->CallNonvirtualObjectMethodA(obj, getHandle(), method, (jvalue*)args); 1016 + handleJavaExceptions(); 1017 + return Object(result, DeleteLocalInput); 1018 + } 1019 + 1020 + Object Class::newObject(method_t constructor, internal::value_t* args) const 1021 + { 1022 + jobject ref = env()->NewObjectA(getHandle(), constructor, (jvalue*)args); 1023 + handleJavaExceptions(); 1024 + return Object(ref, DeleteLocalInput); 1025 + } 1026 + 1027 + /* 1028 + Enum Implementation 1029 + */ 1030 + 1031 + Enum::Enum(const char* name) : Class(name) 1032 + { 1033 + _name = "L"; 1034 + _name += name; 1035 + _name += ";"; 1036 + } 1037 + 1038 + Object Enum::get(const char* name) const 1039 + { 1040 + return Class::get<Object>(getStaticField(name, _name.c_str())); 1041 + } 1042 + 1043 + /* 1044 + Array Implementation 1045 + */ 1046 + 1047 + template <> Array<bool>::Array(long length) : Object(env()->NewBooleanArray(length)), _length(length) 1048 + { 1049 + } 1050 + 1051 + template <> Array<byte_t>::Array(long length) : Object(env()->NewByteArray(length)), _length(length) 1052 + { 1053 + } 1054 + 1055 + template <> Array<wchar_t>::Array(long length) : Object(env()->NewCharArray(length)), _length(length) 1056 + { 1057 + } 1058 + 1059 + template <> Array<short>::Array(long length) : Object(env()->NewShortArray(length)), _length(length) 1060 + { 1061 + } 1062 + 1063 + template <> Array<int>::Array(long length) : Object(env()->NewIntArray(length)), _length(length) 1064 + { 1065 + } 1066 + 1067 + template <> Array<long long>::Array(long length) : Object(env()->NewLongArray(length)), _length(length) 1068 + { 1069 + } 1070 + 1071 + template <> Array<float>::Array(long length) : Object(env()->NewFloatArray(length)), _length(length) 1072 + { 1073 + } 1074 + 1075 + template <> Array<double>::Array(long length) : Object(env()->NewDoubleArray(length)), _length(length) 1076 + { 1077 + } 1078 + 1079 + template <> Array<std::string>::Array(long length) : Object(env()->NewObjectArray(length, Class("java/lang/String").getHandle(), nullptr)), _length(length) 1080 + { 1081 + } 1082 + 1083 + template <> Array<std::wstring>::Array(long length) : Object(env()->NewObjectArray(length, Class("java/lang/String").getHandle(), nullptr)), _length(length) 1084 + { 1085 + } 1086 + 1087 + template <> Array<Object>::Array(long length) : Object(env()->NewObjectArray(length, Class("java/lang/Object").getHandle(), nullptr)), _length(length) 1088 + { 1089 + } 1090 + 1091 + template <> Array<Object>::Array(long length, const Class& type) : Object(env()->NewObjectArray(length, type.getHandle(), nullptr)), _length(length) 1092 + { 1093 + } 1094 + 1095 + template <> bool Array<bool>::getElement(long index) const 1096 + { 1097 + jboolean output; 1098 + env()->GetBooleanArrayRegion(jbooleanArray(getHandle()), index, 1, &output); 1099 + handleJavaExceptions(); 1100 + return output; 1101 + } 1102 + 1103 + template <> byte_t Array<byte_t>::getElement(long index) const 1104 + { 1105 + jbyte output; 1106 + env()->GetByteArrayRegion(jbyteArray(getHandle()), index, 1, &output); 1107 + handleJavaExceptions(); 1108 + return output; 1109 + } 1110 + 1111 + template <> wchar_t Array<wchar_t>::getElement(long index) const 1112 + { 1113 + jchar output; 1114 + env()->GetCharArrayRegion(jcharArray(getHandle()), index, 1, &output); 1115 + handleJavaExceptions(); 1116 + return output; 1117 + } 1118 + 1119 + template <> short Array<short>::getElement(long index) const 1120 + { 1121 + jshort output; 1122 + env()->GetShortArrayRegion(jshortArray(getHandle()), index, 1, &output); 1123 + handleJavaExceptions(); 1124 + return output; 1125 + } 1126 + 1127 + template <> int Array<int>::getElement(long index) const 1128 + { 1129 + jint output; 1130 + env()->GetIntArrayRegion(jintArray(getHandle()), index, 1, &output); 1131 + handleJavaExceptions(); 1132 + return output; 1133 + } 1134 + 1135 + template <> long long Array<long long>::getElement(long index) const 1136 + { 1137 + jlong output; 1138 + env()->GetLongArrayRegion(jlongArray(getHandle()), index, 1, &output); 1139 + handleJavaExceptions(); 1140 + return output; 1141 + } 1142 + 1143 + template <> float Array<float>::getElement(long index) const 1144 + { 1145 + jfloat output; 1146 + env()->GetFloatArrayRegion(jfloatArray(getHandle()), index, 1, &output); 1147 + handleJavaExceptions(); 1148 + return output; 1149 + } 1150 + 1151 + template <> double Array<double>::getElement(long index) const 1152 + { 1153 + jdouble output; 1154 + env()->GetDoubleArrayRegion(jdoubleArray(getHandle()), index, 1, &output); 1155 + handleJavaExceptions(); 1156 + return output; 1157 + } 1158 + 1159 + template <> std::string Array<std::string>::getElement(long index) const 1160 + { 1161 + jobject output = env()->GetObjectArrayElement(jobjectArray(getHandle()), index); 1162 + handleJavaExceptions(); 1163 + return toString(output); 1164 + } 1165 + 1166 + template <> std::wstring Array<std::wstring>::getElement(long index) const 1167 + { 1168 + jobject output = env()->GetObjectArrayElement(jobjectArray(getHandle()), index); 1169 + handleJavaExceptions(); 1170 + return toWString(output); 1171 + } 1172 + 1173 + template <> Object Array<Object>::getElement(long index) const 1174 + { 1175 + jobject output = env()->GetObjectArrayElement(jobjectArray(getHandle()), index); 1176 + handleJavaExceptions(); 1177 + return Object(output, DeleteLocalInput); 1178 + } 1179 + 1180 + template <> void Array<bool>::setElement(long index, bool value) 1181 + { 1182 + jboolean jvalue = value; 1183 + env()->SetBooleanArrayRegion(jbooleanArray(getHandle()), index, 1, &jvalue); 1184 + handleJavaExceptions(); 1185 + } 1186 + 1187 + template <> void Array<byte_t>::setElement(long index, byte_t value) 1188 + { 1189 + jbyte jvalue = value; 1190 + env()->SetByteArrayRegion(jbyteArray(getHandle()), index, 1, &jvalue); 1191 + handleJavaExceptions(); 1192 + } 1193 + 1194 + template <> void Array<wchar_t>::setElement(long index, wchar_t value) 1195 + { 1196 + jchar jvalue = value; 1197 + env()->SetCharArrayRegion(jcharArray(getHandle()), index, 1, &jvalue); 1198 + handleJavaExceptions(); 1199 + } 1200 + 1201 + template <> void Array<short>::setElement(long index, short value) 1202 + { 1203 + jshort jvalue = value; 1204 + env()->SetShortArrayRegion(jshortArray(getHandle()), index, 1, &jvalue); 1205 + handleJavaExceptions(); 1206 + } 1207 + 1208 + template <> void Array<int>::setElement(long index, int value) 1209 + { 1210 + jint jvalue = value; 1211 + env()->SetIntArrayRegion(jintArray(getHandle()), index, 1, &jvalue); 1212 + handleJavaExceptions(); 1213 + } 1214 + 1215 + template <> void Array<long long>::setElement(long index, long long value) 1216 + { 1217 + jlong jvalue = value; 1218 + env()->SetLongArrayRegion(jlongArray(getHandle()), index, 1, &jvalue); 1219 + handleJavaExceptions(); 1220 + } 1221 + 1222 + template <> void Array<float>::setElement(long index, float value) 1223 + { 1224 + jfloat jvalue = value; 1225 + env()->SetFloatArrayRegion(jfloatArray(getHandle()), index, 1, &jvalue); 1226 + handleJavaExceptions(); 1227 + } 1228 + 1229 + template <> void Array<double>::setElement(long index, double value) 1230 + { 1231 + jdouble jvalue = value; 1232 + env()->SetDoubleArrayRegion(jdoubleArray(getHandle()), index, 1, &jvalue); 1233 + handleJavaExceptions(); 1234 + } 1235 + 1236 + template <> void Array<std::string>::setElement(long index, std::string value) 1237 + { 1238 + JNIEnv* env = jni::env(); 1239 + 1240 + jobject jvalue = env->NewStringUTF(value.c_str());; 1241 + env->SetObjectArrayElement(jobjectArray(getHandle()), index, jvalue); 1242 + env->DeleteLocalRef(jvalue); 1243 + handleJavaExceptions(); 1244 + } 1245 + 1246 + template <> void Array<std::wstring>::setElement(long index, std::wstring value) 1247 + { 1248 + JNIEnv* env = jni::env(); 1249 + 1250 + #ifdef _WIN32 1251 + jobject jvalue = env->NewString((const jchar*) value.c_str(), jsize(value.length())); 1252 + #else 1253 + auto jstr = toJString(value.c_str(), value.length()); 1254 + jobject jvalue = env->NewString(jstr.c_str(), jsize(jstr.length())); 1255 + #endif 1256 + env->SetObjectArrayElement(jobjectArray(getHandle()), index, jvalue); 1257 + env->DeleteLocalRef(jvalue); 1258 + handleJavaExceptions(); 1259 + } 1260 + 1261 + template <> void Array<Object>::setElement(long index, Object value) 1262 + { 1263 + env()->SetObjectArrayElement(jobjectArray(getHandle()), index, value.getHandle()); 1264 + handleJavaExceptions(); 1265 + } 1266 + 1267 + /* 1268 + Vm Implementation 1269 + */ 1270 + 1271 + typedef jint (JNICALL *CreateVm_t)(JavaVM**, void**, void*); 1272 + 1273 + 1274 + static std::string detectJvmPath() 1275 + { 1276 + std::string result; 1277 + 1278 + #ifdef _WIN32 1279 + 1280 + BYTE buffer[1024]; 1281 + DWORD size = sizeof(buffer); 1282 + HKEY versionKey; 1283 + 1284 + // Search via registry entries. 1285 + if (::RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\JavaSoft\\Java Runtime Environment\\", &versionKey) == ERROR_SUCCESS) 1286 + { 1287 + if (::RegQueryValueEx(versionKey, "CurrentVersion", NULL, NULL, buffer, &size) == ERROR_SUCCESS) 1288 + { 1289 + HKEY libKey; 1290 + 1291 + std::string keyName = std::string("Software\\JavaSoft\\Java Runtime Environment\\") + (const char*)buffer; 1292 + 1293 + ::RegCloseKey(versionKey); 1294 + 1295 + if (::RegOpenKeyA(HKEY_LOCAL_MACHINE, keyName.c_str(), &libKey) == ERROR_SUCCESS) 1296 + { 1297 + size = sizeof(buffer); 1298 + 1299 + if (::RegQueryValueEx(libKey, "RuntimeLib", NULL, NULL, buffer, &size) == ERROR_SUCCESS) 1300 + { 1301 + result = (const char*)buffer; 1302 + } 1303 + 1304 + ::RegCloseKey(libKey); 1305 + } 1306 + } 1307 + } 1308 + 1309 + if (result.length() == 0) 1310 + { 1311 + // Could not locate via registry. Try the JAVA_HOME environment variable. 1312 + if ((size = ::GetEnvironmentVariableA("JAVA_HOME", (LPSTR) buffer, sizeof(buffer))) != 0) 1313 + { 1314 + std::string javaHome((const char*) buffer, size); 1315 + 1316 + // Different installers put in different relative locations. 1317 + std::string options[] = { 1318 + javaHome + "\\jre\\bin\\client\\jvm.dll", 1319 + javaHome + "\\jre\\bin\\server\\jvm.dll", 1320 + javaHome + "\\bin\\client\\jvm.dll", 1321 + javaHome + "\\bin\\server\\jvm.dll" 1322 + }; 1323 + 1324 + for (auto i : options) 1325 + if (fileExists(i)) 1326 + return i; 1327 + } 1328 + } 1329 + 1330 + #else 1331 + 1332 + const char* javaHome = getenv("JAVA_HOME"); 1333 + if (javaHome != nullptr) { 1334 + #ifdef __APPLE__ 1335 + std::string libJvmPath = std::string(javaHome) + "/jre/lib/server/libjvm.dylib"; 1336 + #else 1337 + std::string libJvmPath = std::string(javaHome) + "/jre/lib/amd64/server/libjvm.so"; 1338 + #endif 1339 + result = libJvmPath; 1340 + } else { 1341 + // Best guess so far. 1342 + result = "/usr/lib/jvm/default-java/jre/lib/amd64/server/libjvm.so"; 1343 + } 1344 + 1345 + #endif // _WIN32 1346 + 1347 + return result; 1348 + } 1349 + 1350 + Vm::Vm(const char* path_) 1351 + { 1352 + bool expected = false; 1353 + 1354 + std::string path = path_ ? path_ : detectJvmPath(); 1355 + 1356 + if (path.length() == 0) 1357 + throw InitializationException("Could not locate Java Virtual Machine"); 1358 + if (!isVm.compare_exchange_strong(expected, true)) 1359 + throw InitializationException("Java Virtual Machine already initialized"); 1360 + 1361 + if (javaVm == nullptr) 1362 + { 1363 + JNIEnv* env; 1364 + JavaVMInitArgs args = {}; 1365 + args.version = JNI_VERSION_1_2; 1366 + 1367 + #ifdef _WIN32 1368 + 1369 + HMODULE lib = ::LoadLibraryA(path.c_str()); 1370 + 1371 + if (lib == NULL) 1372 + { 1373 + isVm.store(false); 1374 + throw InitializationException("Could not load JVM library"); 1375 + } 1376 + 1377 + CreateVm_t JNI_CreateJavaVM = (CreateVm_t) ::GetProcAddress(lib, "JNI_CreateJavaVM"); 1378 + 1379 + /** 1380 + Is your debugger catching an error here? This is normal. Just continue. The JVM 1381 + intentionally does this to test how the OS handles memory-reference exceptions. 1382 + */ 1383 + if (JNI_CreateJavaVM == NULL || JNI_CreateJavaVM(&javaVm, (void**) &env, &args) != 0) 1384 + { 1385 + isVm.store(false); 1386 + ::FreeLibrary(lib); 1387 + throw InitializationException("Java Virtual Machine failed during creation"); 1388 + } 1389 + 1390 + #else 1391 + 1392 + void* lib = ::dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL); 1393 + 1394 + if (lib == NULL) 1395 + { 1396 + isVm.store(false); 1397 + throw InitializationException("Could not load JVM library"); 1398 + } 1399 + 1400 + CreateVm_t JNI_CreateJavaVM = (CreateVm_t) ::dlsym(lib, "JNI_CreateJavaVM"); 1401 + 1402 + if (JNI_CreateJavaVM == NULL || JNI_CreateJavaVM(&javaVm, (void**) &env, &args) != 0) 1403 + { 1404 + isVm.store(false); 1405 + ::dlclose(lib); 1406 + throw InitializationException("Java Virtual Machine failed during creation"); 1407 + } 1408 + 1409 + #endif // _WIN32 1410 + } 1411 + } 1412 + 1413 + Vm::~Vm() 1414 + { 1415 + /* 1416 + Note that you can't ever *really* unload the JavaVM. If you call 1417 + DestroyJavaVM(), you can't then call JNI_CreateJavaVM() again. 1418 + So, instead we just flag it as "gone". 1419 + */ 1420 + isVm.store(false); 1421 + } 1422 + 1423 + // Forward Declarations 1424 + JNIEnv* env(); 1425 + 1426 + #ifndef _WIN32 1427 + extern std::basic_string<jchar> toJString(const wchar_t* str, size_t length); 1428 + #endif 1429 + 1430 + namespace internal 1431 + { 1432 + // Base Type Conversions 1433 + void valueArg(value_t* v, bool a) { ((jvalue*) v)->z = jboolean(a); } 1434 + void valueArg(value_t* v, byte_t a) { ((jvalue*) v)->b = a; } 1435 + void valueArg(value_t* v, wchar_t a) { ((jvalue*) v)->c = jchar(a); } // Note: Possible truncation. 1436 + void valueArg(value_t* v, short a) { ((jvalue*) v)->s = a; } 1437 + void valueArg(value_t* v, int a) { ((jvalue*) v)->i = a; } 1438 + void valueArg(value_t* v, long long a) { ((jvalue*) v)->j = a; } 1439 + void valueArg(value_t* v, float a) { ((jvalue*) v)->f = a; } 1440 + void valueArg(value_t* v, double a) { ((jvalue*) v)->d = a; } 1441 + void valueArg(value_t* v, jobject a) { ((jvalue*) v)->l = a; } 1442 + void valueArg(value_t* v, const Object& a) { ((jvalue*) v)->l = a.getHandle(); } 1443 + void valueArg(value_t* v, const Object* const& a) { ((jvalue*) v)->l = a ? a->getHandle() : nullptr; } 1444 + 1445 + /* 1446 + Object Implementations 1447 + */ 1448 + 1449 + std::string valueSig(const Object* obj) 1450 + { 1451 + if (obj == nullptr || obj->isNull()) 1452 + return "Ljava/lang/Object;"; // One can always hope... 1453 + 1454 + std::string name = Class(obj->getClass(), Object::Temporary).getName(); 1455 + 1456 + // Change from "java.lang.Object" format to "java/lang/Object"; 1457 + for (size_t i = 0; i < name.length(); ++i) 1458 + if (name[i] == '.') 1459 + name[i] = '/'; 1460 + 1461 + return "L" + name + ";"; 1462 + } 1463 + 1464 + /* 1465 + String Implementations 1466 + */ 1467 + 1468 + void valueArg(value_t* v, const std::string& a) 1469 + { 1470 + ((jvalue*) v)->l = env()->NewStringUTF(a.c_str()); 1471 + } 1472 + 1473 + template <> void cleanupArg<std::string>(value_t* v) 1474 + { 1475 + env()->DeleteLocalRef(((jvalue*) v)->l); 1476 + } 1477 + 1478 + void valueArg(value_t* v, const char* a) 1479 + { 1480 + ((jvalue*) v)->l = env()->NewStringUTF(a); 1481 + } 1482 + 1483 + 1484 + template <> void cleanupArg<const char*>(value_t* v) 1485 + { 1486 + env()->DeleteLocalRef(((jvalue*) v)->l); 1487 + } 1488 + #ifdef _WIN32 1489 + 1490 + void valueArg(value_t* v, const std::wstring& a) 1491 + { 1492 + ((jvalue*) v)->l = env()->NewString((const jchar*) a.c_str(), jsize(a.length())); 1493 + } 1494 + 1495 + void valueArg(value_t* v, const wchar_t* a) 1496 + { 1497 + ((jvalue*) v)->l = env()->NewString((const jchar*) a, jsize(std::wcslen(a))); 1498 + } 1499 + #else 1500 + 1501 + void valueArg(value_t* v, const std::wstring& a) 1502 + { 1503 + auto jstr = toJString(a.c_str(), a.length()); 1504 + ((jvalue*) v)->l = env()->NewString(jstr.c_str(), jsize(jstr.length())); 1505 + } 1506 + 1507 + void valueArg(value_t* v, const wchar_t* a) 1508 + { 1509 + auto jstr = toJString(a, std::wcslen(a)); 1510 + ((jvalue*) v)->l = env()->NewString(jstr.c_str(), jsize(jstr.length())); 1511 + } 1512 + 1513 + #endif 1514 + 1515 + template <> void cleanupArg<const std::wstring*>(value_t* v) 1516 + { 1517 + env()->DeleteLocalRef(((jvalue*) v)->l); 1518 + } 1519 + 1520 + template <> void cleanupArg<const wchar_t*>(value_t* v) 1521 + { 1522 + env()->DeleteLocalRef(((jvalue*) v)->l); 1523 + } 1524 + 1525 + long getArrayLength(jarray array) 1526 + { 1527 + return env()->GetArrayLength(array); 1528 + } 1529 + } 1530 + } 1531 +
+1036
src/external/jnipp/jnipp.h
··· 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 10 + struct JNIEnv_; 11 + struct _JNIEnv; 12 + struct JavaVM_; 13 + struct _JavaVM; 14 + struct _jmethodID; 15 + struct _jfieldID; 16 + class _jobject; 17 + class _jclass; 18 + class _jarray; 19 + 20 + namespace 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 + 77 + /** 78 + This namespace is for messy implementation details only. It is not a part 79 + of the external API and is subject to change at any time. It is only in a 80 + header file due to the fact it is required by some template functions. 81 + 82 + Long story short... this stuff be messy, yo. 83 + */ 84 + namespace internal 85 + { 86 + /* 87 + Signature Generation 88 + */ 89 + 90 + inline std::string valueSig(const void*) { return "V"; } 91 + inline std::string valueSig(const bool*) { return "Z"; } 92 + inline std::string valueSig(const byte_t*) { return "B"; } 93 + inline std::string valueSig(const wchar_t*) { return "C"; } 94 + inline std::string valueSig(const short*) { return "S"; } 95 + inline std::string valueSig(const int*) { return "I"; } 96 + inline std::string valueSig(const long long*) { return "J"; } 97 + inline std::string valueSig(const float*) { return "F"; } 98 + inline std::string valueSig(const double*) { return "D"; } 99 + inline std::string valueSig(const std::string*) { return "Ljava/lang/String;"; } 100 + inline std::string valueSig(const std::wstring*) { return "Ljava/lang/String;"; } 101 + inline std::string valueSig(const char* const*) { return "Ljava/lang/String;"; } 102 + inline std::string valueSig(const wchar_t* const*) { return "Ljava/lang/String;"; } 103 + std::string valueSig(const Object* obj); 104 + inline std::string valueSig(const Object* const* obj) { return valueSig(obj ? *obj : nullptr); } 105 + 106 + template <int n, class TArg> 107 + inline std::string valueSig(const TArg(*arg)[n]) { return valueSig((const TArg* const*)arg); } 108 + 109 + inline std::string sig() { return ""; } 110 + 111 + template <class TArg, class... TArgs> 112 + std::string sig(const TArg& arg, const TArgs&... args) { 113 + return valueSig(&arg) + sig(args...); 114 + } 115 + 116 + /* 117 + Argument Conversion 118 + */ 119 + 120 + typedef long long value_t; 121 + 122 + void valueArg(value_t* v, bool a); 123 + void valueArg(value_t* v, byte_t a); 124 + void valueArg(value_t* v, wchar_t a); 125 + void valueArg(value_t* v, short a); 126 + void valueArg(value_t* v, int a); 127 + void valueArg(value_t* v, long long a); 128 + void valueArg(value_t* v, float a); 129 + void valueArg(value_t* v, double a); 130 + void valueArg(value_t* v, jobject a); 131 + void valueArg(value_t* v, const Object& a); 132 + void valueArg(value_t* v, const Object* const& a); 133 + void valueArg(value_t* v, const std::string& a); 134 + void valueArg(value_t* v, const char* a); 135 + void valueArg(value_t* v, const std::wstring& a); 136 + void valueArg(value_t* v, const wchar_t* a); 137 + 138 + inline void args(value_t*) {} 139 + 140 + template <class TArg, class... TArgs> 141 + void args(value_t* values, const TArg& arg, const TArgs&... args) { 142 + valueArg(values, arg); 143 + internal::args(values + 1, args...); 144 + } 145 + 146 + template <class TArg> void cleanupArg(value_t* /* value */) {} 147 + template <> void cleanupArg<std::string>(value_t* value); 148 + template <> void cleanupArg<std::wstring>(value_t* value); 149 + template <> void cleanupArg<const char*>(value_t* value); 150 + template <> void cleanupArg<const wchar_t*>(value_t* value); 151 + 152 + template <class TArg = void, class... TArgs> 153 + void cleanupArgs(value_t* values) { 154 + cleanupArg<TArg>(values); 155 + cleanupArgs<TArgs...>(values + 1); 156 + } 157 + 158 + template <> 159 + inline void cleanupArgs<void>(value_t* /* values */) {} 160 + 161 + template <class... TArgs> 162 + class ArgArray 163 + { 164 + public: 165 + ArgArray(const TArgs&... args) { 166 + std::memset(this, 0, sizeof(ArgArray<TArgs...>)); 167 + internal::args(values, args...); 168 + } 169 + 170 + ~ArgArray() { 171 + cleanupArgs<TArgs...>(values); 172 + } 173 + 174 + value_t values[sizeof...(TArgs)]; 175 + }; 176 + 177 + long getArrayLength(jarray array); 178 + } 179 + 180 + /** 181 + Initialises the Java Native Interface with the given JNIEnv handle, which 182 + gets passed into a native function which is called from Java. This only 183 + needs to be done once per process - further calls are no-ops. 184 + \param env A JNI environment handle. 185 + */ 186 + void init(JNIEnv* env); 187 + /** 188 + Initialises the Java Native Interface with the given JavaVM handle, 189 + which may be accessible. This (or the other overload) only needs to be 190 + done once per process - further calls are no-ops. 191 + \param vm A JNI VM handle. 192 + */ 193 + void init(JavaVM* vm); 194 + 195 + /** 196 + Get the appropriate JNI environment for this thread. 197 + */ 198 + JNIEnv* env(); 199 + 200 + /** 201 + Object corresponds with a `java.lang.Object` instance. With an Object, 202 + you can then call Java methods, and access fields on the Object. To 203 + instantiate an Object of a given class, use the `Class` class. 204 + */ 205 + class Object 206 + { 207 + public: 208 + /** Flags which can be passed to the Object constructor. */ 209 + enum ScopeFlags 210 + { 211 + Temporary = 1, ///< Temporary object. Do not create a global reference. 212 + DeleteLocalInput = 2 ///< The input reference is temporary and can be deleted. 213 + }; 214 + 215 + /** Default constructor. Creates a `null` object. */ 216 + Object() noexcept; 217 + 218 + /** 219 + Copies a reference to another Object. Note that this is not a deep 220 + copy operation, and both Objects will reference the same Java 221 + Object. 222 + \param other The Object to copy. 223 + */ 224 + Object(const Object& other); 225 + 226 + /** 227 + Move constructor. Copies the Object reference from the supplied 228 + Object, and then nulls the supplied Object reference. 229 + \param other The Object to move. 230 + */ 231 + Object(Object&& other) noexcept; 232 + 233 + /** 234 + Creates an Object from a local JNI reference. 235 + \param ref The local JNI reference. 236 + \param scopeFlags Bitmask of ScopeFlags values. 237 + */ 238 + Object(jobject ref, int scopeFlags = 0); 239 + 240 + /** 241 + Destructor. Releases this reference on the Java Object so it can be 242 + picked up by the garbage collector. 243 + */ 244 + virtual ~Object() noexcept; 245 + 246 + /** 247 + Assignment operator. Copies the object reference from the supplied 248 + Object. They will now both point to the same Java Object. 249 + \param other The Object to copy. 250 + \return This Object. 251 + */ 252 + Object& operator=(const Object& other); 253 + 254 + /** 255 + Assignment operator. Moves the object reference from the supplied 256 + Object to this one, and leaves the other one as a null. 257 + \param other The Object to move. 258 + \return This Object. 259 + */ 260 + Object& operator=(Object&& other); 261 + 262 + /** 263 + Tells whether the two Objects refer to the same Java Object. 264 + \param other the Object to compare with. 265 + \return `true` if the same, `false` otherwise. 266 + */ 267 + bool operator==(const Object& other) const; 268 + 269 + /** 270 + Tells whether the two Objects refer to the same Java Object. 271 + \param other the Object to compare with. 272 + \return `true` if the different, `false` otherwise. 273 + */ 274 + bool operator!=(const Object& other) const { return !operator==(other); } 275 + 276 + /** 277 + Calls the given method on this Object. The method should have no 278 + parameters. Note that the return type should be explicitly stated 279 + in the function call. 280 + \param method A method handle which applies to this Object. 281 + \return The method's return value. 282 + */ 283 + template <class TReturn> 284 + TReturn call(method_t method) const { return callMethod<TReturn>(method, nullptr); } 285 + 286 + /** 287 + Calls the method on this Object with the given name, and no arguments. 288 + Note that the return type should be explicitly stated in the function 289 + call. 290 + \param name The name of the method to call (with optional signature). 291 + \return The method's return value. 292 + */ 293 + template <class TReturn> 294 + TReturn call(const char* name) const { 295 + if (std::strstr(name, "()")) 296 + return call<TReturn>(getMethod(name)); 297 + 298 + // No signature supplied. Generate our own. 299 + method_t method = getMethod(name, ("()" + internal::valueSig((TReturn*) nullptr)).c_str()); 300 + return call<TReturn>(method); 301 + } 302 + 303 + /** 304 + Calls the method on this Object and supplies the given arguments. 305 + Note that the return type should be explicitly stated in the function 306 + call. 307 + \param method The method to call. 308 + \param args Arguments to supply to the method. 309 + \return The method's return value. 310 + */ 311 + template <class TReturn, class... TArgs> 312 + TReturn call(method_t method, const TArgs&... args) const { 313 + internal::ArgArray<TArgs...> transform(args...); 314 + return callMethod<TReturn>(method, transform.values); 315 + } 316 + 317 + /** 318 + Calls the method on this Object and supplies the given arguments. 319 + Note that the return type should be explicitly stated in the function 320 + call. The type signature of the method is calculated by the types of 321 + the supplied arguments. 322 + \param name The name of the method to call (and optional signature). 323 + \param args Arguments to supply to the method. 324 + \return The method's return value. 325 + */ 326 + template <class TReturn, class... TArgs> 327 + TReturn call(const char* name, const TArgs&... args) const { 328 + if (std::strchr(name, '(')) 329 + return call<TReturn>(getMethod(name), args...); 330 + 331 + std::string sig = "(" + internal::sig(args...) + ")" + internal::valueSig((TReturn*) nullptr); 332 + method_t method = getMethod(name, sig.c_str()); 333 + return call<TReturn>(method, args...); 334 + } 335 + 336 + /** 337 + Gets a field value from this Object. The field must belong to the 338 + Object's class. Note that the field type should be explicitly stated 339 + in the function call. 340 + \param field Identifier for the field to retrieve. 341 + \return The field's value. 342 + */ 343 + template <class TType> 344 + TType get(field_t field) const; 345 + 346 + /** 347 + Gets a field value from this Object. The field must belong to the 348 + Object's class. Note that the field type should be explicitly stated 349 + in the function call. 350 + \param name The name of the field to retrieve. 351 + \return The field's value. 352 + */ 353 + template <class TType> 354 + TType get(const char* name) const { 355 + field_t field = getField(name, internal::valueSig((TType*) nullptr).c_str()); 356 + return get<TType>(field); 357 + } 358 + 359 + /** 360 + Sets a field's value on this Object. The field must belong to the 361 + Object's class, and the parameter's type should correspond to the 362 + type of the field. 363 + \param field The field to set the value to. 364 + \param value The value to set. 365 + */ 366 + template <class TType> 367 + void set(field_t field, const TType& value); 368 + 369 + /** 370 + Sets a field's value on this Object. The field must belong to the 371 + Object's class, and the parameter's type should correspond to the 372 + type of the field. 373 + \param name The name of the field to set the value to. 374 + \param value The value to set. 375 + */ 376 + template <class TType> 377 + void set(const char* name, const TType& value) { 378 + field_t field = getField(name, internal::valueSig((TType*) nullptr).c_str()); 379 + set(field, value); 380 + } 381 + 382 + /** 383 + Tells whether this Object is currently a `null` pointer. 384 + \return `true` if `null`, `false` if it references an object. 385 + */ 386 + bool isNull() const noexcept; 387 + 388 + /** 389 + Gets a handle for this Object's class. Ideally, this should just return a Class, 390 + but C++ won't let us do that that. 391 + \return The Object's Class's handle. 392 + */ 393 + jclass getClass() const; 394 + 395 + /** 396 + Gets the underlying JNI jobject handle. 397 + \return The JNI handle. 398 + */ 399 + jobject getHandle() const noexcept { return _handle; } 400 + 401 + /** 402 + Create a local reference for the underlying JNI handle. 403 + \return The local reference. 404 + */ 405 + jobject makeLocalReference() const; 406 + 407 + private: 408 + // Helper Functions 409 + method_t getMethod(const char* name, const char* signature) const; 410 + method_t getMethod(const char* nameAndSignature) const; 411 + field_t getField(const char* name, const char* signature) const; 412 + template <class TType> TType callMethod(method_t method, internal::value_t* values) const; 413 + 414 + // Instance Variables 415 + jobject _handle; 416 + mutable jclass _class; 417 + bool _isGlobal; 418 + }; 419 + 420 + /** 421 + Class corresponds with `java.lang.Class`, and allows you to instantiate 422 + Objects and get class members such as methods and fields. 423 + */ 424 + class Class : protected Object 425 + { 426 + public: 427 + /** 428 + Creates a null class reference. 429 + */ 430 + Class() : Object() {} 431 + 432 + /** 433 + Obtains a class reference to the Java class with the given qualified 434 + name. 435 + \param name The qualified class name (e.g. "java/lang/String"). 436 + */ 437 + Class(const char* name); 438 + 439 + /** 440 + Creates a Class object by JNI reference. 441 + \param ref The JNI class reference. 442 + \param scopeFlags Bitmask of Object::ScopeFlags. 443 + */ 444 + Class(jclass ref, int scopeFlags = Temporary); 445 + 446 + /** 447 + Tells whether this Class is null or valid. 448 + \return `true` if null, `false` if valid. 449 + */ 450 + bool isNull() const noexcept { return Object::isNull(); } 451 + 452 + /** 453 + Creates a new instance of this Java class and returns a reference to 454 + it. The item's parameterless constructor is called. 455 + \return The created instance. 456 + */ 457 + Object newInstance() const; 458 + 459 + /** 460 + Creates a new instance of this Java class and returns a reference to 461 + it. 462 + \param constructor The constructor to call. 463 + \param args Arguments to supply to the constructor. 464 + \return The created instance. 465 + */ 466 + template <class... TArgs> 467 + Object newInstance(method_t constructor, const TArgs&... args) const { 468 + internal::ArgArray<TArgs...> transform(args...); 469 + return newObject(constructor, transform.values); 470 + } 471 + 472 + /** 473 + Creates a new instance of this Java class and returns a reference to 474 + it. The constructor signature is determined by the supplied parameters, 475 + and the parameters are then passed to the constructor. 476 + \param args Arguments to supply to the constructor. 477 + \return The created instance. 478 + */ 479 + template <class... TArgs> 480 + Object newInstance(const TArgs&... args) const { 481 + method_t constructor = getMethod("<init>", ("(" + internal::sig(args...) + ")V").c_str()); 482 + return newInstance(constructor, args...); 483 + } 484 + 485 + /** 486 + Gets a handle to the field with the given name and type signature. 487 + This handle can then be stored so that the field does not need to 488 + be looked up by name again. It does not need to be deleted. 489 + \param name The name of the field. 490 + \param signature The JNI type signature of the field. 491 + \return The field ID. 492 + */ 493 + field_t getField(const char* name, const char* signature) const; 494 + 495 + /** 496 + Gets a handle to the field with the given name and the supplied type. 497 + This handle can then be stored so that the field does not need to 498 + be looked up by name again. It does not need to be deleted. 499 + \param name The name of the field. 500 + \return The field ID. 501 + */ 502 + template<typename TType> 503 + field_t getField(const char* name) const { 504 + return getField(name, internal::valueSig((TType*) nullptr).c_str()); 505 + } 506 + 507 + /** 508 + Gets a handle to the static field with the given name and type signature. 509 + This handle can then be stored so that the field does not need to 510 + be looked up by name again. It does not need to be deleted. 511 + \param name The name of the field. 512 + \param signature The JNI type signature of the field. 513 + \return The field ID. 514 + */ 515 + field_t getStaticField(const char* name, const char* signature) const; 516 + 517 + /** 518 + Gets a handle to the static field with the given name and the supplied type. 519 + This handle can then be stored so that the field does not need to 520 + be looked up by name again. It does not need to be deleted. 521 + \param name The name of the field. 522 + \return The field ID. 523 + */ 524 + template<typename TType> 525 + field_t getStaticField(const char* name) const { 526 + return getStaticField(name, internal::valueSig((TType*)nullptr).c_str()); 527 + } 528 + 529 + /** 530 + Gets a handle to the method with the given name and signature. 531 + This handle can then be stored so that the method does not need 532 + to be looked up by name again. It does not need to be deleted. 533 + \param name The name of the method. 534 + \param signature The JNI method signature. 535 + \return The method ID. 536 + */ 537 + method_t getMethod(const char* name, const char* signature) const; 538 + 539 + /** 540 + Gets a handle to the method with the given name and signature. 541 + This handle can then be stored so that the method does not need 542 + to be looked up by name again. It does not need to be deleted. 543 + \param nameAndSignature Name and signature identifier (e.g. "toString()Ljava/lang/String;"). 544 + \return The method ID. 545 + */ 546 + method_t getMethod(const char* nameAndSignature) const; 547 + 548 + /** 549 + Gets a handle to the static method with the given name and signature. 550 + This handle can then be stored so that the method does not need 551 + to be looked up by name again. It does not need to be deleted. 552 + \param name The name of the method. 553 + \param signature The JNI method signature. 554 + \return The method ID. 555 + */ 556 + method_t getStaticMethod(const char* name, const char* signature) const; 557 + 558 + /** 559 + Gets a handle to the static method with the given name and signature. 560 + This handle can then be stored so that the method does not need 561 + to be looked up by name again. It does not need to be deleted. 562 + \param nameAndSignature Name and signature identifier (e.g. "toString()Ljava/lang/String;"). 563 + \return The method ID. 564 + */ 565 + method_t getStaticMethod(const char* nameAndSignature) const; 566 + 567 + /** 568 + Gets a handle to the constructor for this Class with the given 569 + signature. Note that the return type should always be `void` ("V"). 570 + \param signature The JNI method signature for the constructor. 571 + \return The constructor method ID. 572 + */ 573 + method_t getConstructor(const char* signature) const { return getMethod("<init>", signature); } 574 + 575 + /** 576 + Gets the parent Class of this Class. 577 + \return The parent class. 578 + */ 579 + Class getParent() const; 580 + 581 + /** 582 + Gets the JNI-qualified name of this Class. 583 + \return The Class name. 584 + */ 585 + std::string getName() const; 586 + 587 + /** 588 + Calls a static method on this Class. The method should have no 589 + parameters. Note that the return type should be explicitly stated 590 + in the function call. 591 + \param method A method handle which applies to this Object. 592 + \return The method's return value. 593 + */ 594 + template <class TReturn> 595 + TReturn call(method_t method) const { return callStaticMethod<TReturn>(method, nullptr); } 596 + 597 + /** 598 + Calls a static method on this Class with the given name, and no arguments. 599 + Note that the return type should be explicitly stated in the function 600 + call. 601 + \param name The name of the method to call. 602 + \return The method's return value. 603 + */ 604 + template <class TReturn> 605 + TReturn call(const char* name) const { 606 + method_t method = getStaticMethod(name, ("()" + internal::valueSig((TReturn*) nullptr)).c_str()); 607 + return call<TReturn>(method); 608 + } 609 + 610 + /** 611 + Calls a static method on this Class and supplies the given arguments. 612 + Note that the return type should be explicitly stated in the function 613 + call. 614 + \param method The method to call. 615 + \param args Arguments to supply to the method. 616 + \return The method's return value. 617 + */ 618 + template <class TReturn, class... TArgs> 619 + TReturn call(method_t method, const TArgs&... args) const { 620 + internal::ArgArray<TArgs...> transform(args...); 621 + return callStaticMethod<TReturn>(method, transform.values); 622 + } 623 + 624 + /** 625 + Calls a static method on this Class and supplies the given arguments. 626 + Note that the return type should be explicitly stated in the function 627 + call. The type signature of the method is calculated by the types of 628 + the supplied arguments. 629 + \param name The name of the method to call. 630 + \param args Arguments to supply to the method. 631 + \return The method's return value. 632 + */ 633 + template <class TReturn, class... TArgs> 634 + TReturn call(const char* name, const TArgs&... args) const { 635 + if (std::strchr(name, '(')) 636 + return call<TReturn>(getStaticMethod(name), args...); 637 + 638 + std::string sig = "(" + internal::sig(args...) + ")" + internal::valueSig((TReturn*) nullptr); 639 + method_t method = getStaticMethod(name, sig.c_str()); 640 + return call<TReturn>(method, args...); 641 + } 642 + 643 + /** 644 + Calls a non-static method on this Class, applying it to the supplied 645 + Object. The difference between this and Object.call() is that the 646 + specific class implementation of the method is called, rather than 647 + doing a virtual method lookup. 648 + \param obj The Object to call the method on. 649 + \param method The method to call. 650 + \return The method's return value. 651 + */ 652 + template <class TReturn> 653 + TReturn call(const Object& obj, method_t method) const { 654 + return callExactMethod<TReturn>(obj.getHandle(), method, nullptr); 655 + } 656 + 657 + /** 658 + Calls a non-static method on this Class, applying it to the supplied 659 + Object. The difference between this and Object.call() is that the 660 + specific class implementation of the method is called, rather than 661 + doing a virtual method lookup. 662 + \param obj The Object to call the method on. 663 + \param name The name of the method to call. 664 + \return The method's return value. 665 + */ 666 + template <class TReturn> 667 + TReturn call(const Object& obj, const char* name) const { 668 + method_t method = getMethod(name, ("()" + internal::valueSig((TReturn*) nullptr)).c_str()); 669 + return call<TReturn>(obj, method); 670 + } 671 + template <class TReturn> 672 + TReturn call(const Object* obj, const char* name) const { 673 + return call<TReturn>(obj, name); 674 + } 675 + 676 + /** 677 + Calls a non-static method on this Class, applying it to the supplied 678 + Object. The difference between this and Object.call() is that the 679 + specific class implementation of the method is called, rather than 680 + doing a virtual method lookup. 681 + \param obj The Object to call the method on. 682 + \param method The method to call. 683 + \param args Arguments to pass to the method. 684 + \return The method's return value. 685 + */ 686 + template <class TReturn, class... TArgs> 687 + TReturn call(const Object& obj, method_t method, const TArgs&... args) const { 688 + internal::ArgArray<TArgs...> transform(args...); 689 + return callExactMethod<TReturn>(obj.getHandle(), method, transform.values); 690 + } 691 + template <class TReturn, class... TArgs> 692 + TReturn call(const Object* obj, method_t method, const TArgs&... args) const { 693 + return call<TReturn>(*obj, method, args...); 694 + } 695 + 696 + /** 697 + Calls a non-static method on this Class, applying it to the supplied 698 + Object. The difference between this and Object.call() is that the 699 + specific class implementation of the method is called, rather than 700 + doing a virtual method lookup. 701 + \param obj The Object to call the method on. 702 + \param name The name of the method to call. 703 + \param args Arguments to pass to the method. 704 + \return The method's return value. 705 + */ 706 + template <class TReturn, class... TArgs> 707 + TReturn call(const Object& obj, const char* name, const TArgs&... args) const { 708 + std::string sig = "(" + internal::sig(args...) + ")" + internal::valueSig((TReturn*) nullptr); 709 + method_t method = getMethod(name, sig.c_str()); 710 + return call<TReturn>(obj, method, args...); 711 + } 712 + template <class TReturn, class... TArgs> 713 + TReturn call(const Object* obj, const char* name, const TArgs&... args) const { 714 + return call<TReturn>(*obj, name, args...); 715 + } 716 + 717 + /** 718 + Gets a static field value from this Class. Note that the field type 719 + should be explicitly stated in the function call. 720 + \param field Identifier for the field to retrieve. 721 + \return The field's value. 722 + */ 723 + template <class TType> 724 + TType get(field_t field) const; 725 + 726 + /** 727 + Gets a static field value from this Class. Note that the field type 728 + should be explicitly stated in the function call. 729 + \param name The name of the field to retrieve. 730 + \return The field's value. 731 + */ 732 + template <class TType> 733 + TType get(const char* name) const { 734 + field_t field = getStaticField(name, internal::valueSig((TType*) nullptr).c_str()); 735 + return get<TType>(field); 736 + } 737 + 738 + /** 739 + Sets a static field's value on this Class. The parameter's type should 740 + correspond to the type of the field. 741 + \param field The field to set the value to. 742 + \param value The value to set. 743 + */ 744 + template <class TType> 745 + void set(field_t field, const TType& value); 746 + 747 + /** 748 + Sets a static field's value on this Class. The parameter's type 749 + should correspond to the type of the field. 750 + \param name The name of the field to set the value to. 751 + \param value The value to set. 752 + */ 753 + template <class TType> 754 + void set(const char* name, const TType& value) { 755 + field_t field = getStaticField(name, internal::valueSig((TType*) nullptr).c_str()); 756 + set(field, value); 757 + } 758 + 759 + /** 760 + Gets the underlying JNI jclass handle. 761 + \return The JNI handle. 762 + */ 763 + jclass getHandle() const noexcept { return jclass(Object::getHandle()); } 764 + 765 + private: 766 + // Helper Functions 767 + template <class TType> TType callStaticMethod(method_t method, internal::value_t* values) const; 768 + template <class TType> TType callExactMethod(jobject obj, method_t method, internal::value_t* values) const; 769 + Object newObject(method_t constructor, internal::value_t* args) const; 770 + }; 771 + 772 + /** 773 + Convenience class for dealing with Java enums. 774 + */ 775 + class Enum : protected Class 776 + { 777 + public: 778 + /** 779 + Loads the Enum with the given JNI-formatted name. 780 + \param name The name of the enum. 781 + */ 782 + Enum(const char* name); 783 + 784 + /** 785 + Gets the enum value with the given name. 786 + \param name The name of the enum value. 787 + \return The enum value identifier. 788 + */ 789 + Object get(const char* name) const; 790 + 791 + private: 792 + // Instance Variables 793 + std::string _name; 794 + }; 795 + 796 + /** 797 + Used to interact with native Java arrays. The element type can be any primitive 798 + type, jni::Object, std::string or std::wstring. 799 + */ 800 + template <class TElement> 801 + class Array : public Object 802 + { 803 + public: 804 + /** 805 + Default constructor. Creates a null array reference. 806 + */ 807 + Array() noexcept; 808 + 809 + /** 810 + Creates a Array object by JNI reference. 811 + \param ref The JNI array reference. 812 + \param scopeFlags Bitmask of Object::ScopeFlags. 813 + */ 814 + Array(jarray ref, int scopeFlags = Temporary); 815 + 816 + /** 817 + Creates an Array of the given length. The elements are default initialised 818 + to zero / null values. 819 + \param length The Array length. 820 + */ 821 + Array(long length); 822 + 823 + /** 824 + Creates an Array of the given length. A Class type is also specified, but can 825 + be left null to default to "java.lang.Object". 826 + \param length The Array length. 827 + \param type The element type. 828 + 829 + */ 830 + Array(long length, const Class& type); 831 + 832 + /** 833 + Copy constructor. Shares a reference to the Java array with the 834 + copied Array object. 835 + \param other The Array to copy. 836 + */ 837 + Array(const Array<TElement>& other); 838 + 839 + /** 840 + Move constructor. Moves the array reference to the new Array, and leaves 841 + the previous Array as a null reference. 842 + \param other The Array to move. 843 + */ 844 + Array(Array<TElement>&& other) noexcept; 845 + 846 + /** 847 + Assignment operator. Copies the array reference from the supplied 848 + Array. They will now both point to the same Java array. 849 + \param other The Array to copy. 850 + \return This Array. 851 + */ 852 + Array<TElement>& operator=(const Array<TElement>& other); 853 + 854 + /** 855 + Assignment operator. Moves the array reference from the supplied 856 + Array to this one, and leaves the other one as a null. 857 + \param other The Array to move. 858 + \return This Array. 859 + */ 860 + Array<TElement>& operator=(Array<TElement>&& other); 861 + 862 + /** 863 + Checks whether these Arrays both reference the same java array. 864 + \param other The Array to compare with. 865 + \return true if the same (or both null), false otherwise. 866 + */ 867 + bool operator==(const Array<TElement>& other) const { return Object::operator==(other); } 868 + 869 + /** 870 + Checks whether these Arrays reference different the java arrays. 871 + \param other The Array to compare with. 872 + \return false if the same (or both null), true otherwise. 873 + */ 874 + bool operator!=(const Array<TElement>& other) const { return !operator==(other); } 875 + 876 + /** 877 + Sets the element value at the given index in the Array. 878 + \param index The zero-based index. 879 + \param value The value to set. 880 + */ 881 + void setElement(long index, TElement value); 882 + 883 + /** 884 + Gets the value at the given index within the Array. 885 + \param index The zero-based index. 886 + \return The element at the given index. 887 + */ 888 + TElement getElement(long index) const; 889 + TElement operator[](long index) const { return getElement(index); } 890 + 891 + /** 892 + Gets the length of this Array. 893 + \return The array length. 894 + */ 895 + long getLength() const; 896 + 897 + /** 898 + Gets the underlying JNI jarray handle. 899 + \return The JNI handle. 900 + */ 901 + jarray getHandle() const noexcept { return jarray(Object::getHandle()); } 902 + 903 + private: 904 + // Instance Variables 905 + mutable long _length; ///< Mutable as it may only finally get set in a getLength() call. 906 + }; 907 + 908 + /** 909 + When the application's entry point is in C++ rather than in Java, it will 910 + need to spin up its own instance of the Java Virtual Machine (JVM) before 911 + it can initialize the Java Native Interface. Vm is used to create and 912 + destroy a running JVM instance. 913 + 914 + It uses the RAII idiom, so when the destructor is called, the Vm is shut 915 + down. 916 + 917 + Note that currently only one instance is supported. Attempts to create 918 + more will result in an InitializationException. 919 + */ 920 + class Vm final 921 + { 922 + public: 923 + /** 924 + Starts the Java Virtual Machine. 925 + \param path The path to the jvm.dll (or null for auto-detect). 926 + */ 927 + Vm(const char* path = nullptr); 928 + 929 + /** Destroys the running instance of the JVM. */ 930 + ~Vm(); 931 + }; 932 + 933 + /** 934 + A Java method call threw an Exception. 935 + */ 936 + class InvocationException : public Exception 937 + { 938 + public: 939 + /** 940 + Constructor with an error message. 941 + \param msg Message to pass to the Exception. 942 + */ 943 + InvocationException(const char* msg = "Java Exception detected") : Exception(msg) {} 944 + }; 945 + 946 + /** 947 + A supplied name or type signature could not be resolved. 948 + */ 949 + class NameResolutionException : public Exception 950 + { 951 + public: 952 + /** 953 + Constructor with an error message. 954 + \param name The name of the unresolved symbol. 955 + */ 956 + NameResolutionException(const char* name) : Exception(name) {} 957 + }; 958 + 959 + /** 960 + The Java Native Interface was not properly initialized. 961 + */ 962 + class InitializationException : public Exception 963 + { 964 + public: 965 + /** 966 + Constructor with an error message. 967 + \param msg Message to pass to the Exception. 968 + */ 969 + InitializationException(const char* msg) : Exception(msg) {} 970 + }; 971 + 972 + /* 973 + Array Implementation 974 + */ 975 + 976 + template <class TElement> 977 + Array<TElement>::Array() noexcept : Object(), _length(0) 978 + { 979 + } 980 + 981 + template <class TElement> 982 + Array<TElement>::Array(jarray ref, int scopeFlags) : Object((jobject) ref, scopeFlags), _length(-1) 983 + { 984 + } 985 + 986 + template <class TElement> 987 + Array<TElement>::Array(const Array<TElement>& other) : Object(other), _length(other._length) 988 + { 989 + } 990 + 991 + template <class TElement> 992 + Array<TElement>::Array(Array<TElement>&& other) noexcept : Object((Object&&)other), _length(other._length) 993 + { 994 + other._length = 0; 995 + } 996 + 997 + template <class TElement> 998 + Array<TElement>& Array<TElement>::operator=(const Array<TElement>& other) 999 + { 1000 + if (&other != this) 1001 + { 1002 + Object::operator=(other); 1003 + _length = other._length; 1004 + } 1005 + 1006 + return *this; 1007 + } 1008 + 1009 + template <class TElement> 1010 + Array<TElement>& Array<TElement>::operator=(Array<TElement>&& other) 1011 + { 1012 + if (&other != this) 1013 + { 1014 + Object::operator=((Object&&) other); 1015 + _length = other._length; 1016 + 1017 + other._length = 0; 1018 + } 1019 + 1020 + return *this; 1021 + } 1022 + 1023 + template <class TElement> 1024 + long Array<TElement>::getLength() const 1025 + { 1026 + if (_length < 0) 1027 + { 1028 + _length = internal::getArrayLength(getHandle()); 1029 + } 1030 + 1031 + return _length; 1032 + } 1033 + } 1034 + 1035 + #endif // _JNIPP_H_ 1036 +
+45
src/external/jnipp/jnipp.sln
··· 1 +  2 + Microsoft Visual Studio Solution File, Format Version 12.00 3 + # Visual Studio 14 4 + VisualStudioVersion = 14.0.25420.1 5 + MinimumVisualStudioVersion = 10.0.40219.1 6 + Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jnipp", "jnipp.vcxproj", "{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}" 7 + EndProject 8 + Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution Files", "{5A4C5782-6F86-4413-9E19-3F6539DCD835}" 9 + ProjectSection(SolutionItems) = preProject 10 + LICENSE = LICENSE 11 + makefile = makefile 12 + README.md = README.md 13 + EndProjectSection 14 + EndProject 15 + Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "tests", "tests\tests.vcxproj", "{911DB449-3D76-4261-8FFD-9BA508ED1D5B}" 16 + EndProject 17 + Global 18 + GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 + Debug|x64 = Debug|x64 20 + Debug|x86 = Debug|x86 21 + Release|x64 = Release|x64 22 + Release|x86 = Release|x86 23 + EndGlobalSection 24 + GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 + {A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Debug|x64.ActiveCfg = Debug|x64 26 + {A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Debug|x64.Build.0 = Debug|x64 27 + {A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Debug|x86.ActiveCfg = Debug|Win32 28 + {A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Debug|x86.Build.0 = Debug|Win32 29 + {A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Release|x64.ActiveCfg = Release|x64 30 + {A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Release|x64.Build.0 = Release|x64 31 + {A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Release|x86.ActiveCfg = Release|Win32 32 + {A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}.Release|x86.Build.0 = Release|Win32 33 + {911DB449-3D76-4261-8FFD-9BA508ED1D5B}.Debug|x64.ActiveCfg = Debug|x64 34 + {911DB449-3D76-4261-8FFD-9BA508ED1D5B}.Debug|x64.Build.0 = Debug|x64 35 + {911DB449-3D76-4261-8FFD-9BA508ED1D5B}.Debug|x86.ActiveCfg = Debug|Win32 36 + {911DB449-3D76-4261-8FFD-9BA508ED1D5B}.Debug|x86.Build.0 = Debug|Win32 37 + {911DB449-3D76-4261-8FFD-9BA508ED1D5B}.Release|x64.ActiveCfg = Release|x64 38 + {911DB449-3D76-4261-8FFD-9BA508ED1D5B}.Release|x64.Build.0 = Release|x64 39 + {911DB449-3D76-4261-8FFD-9BA508ED1D5B}.Release|x86.ActiveCfg = Release|Win32 40 + {911DB449-3D76-4261-8FFD-9BA508ED1D5B}.Release|x86.Build.0 = Release|Win32 41 + EndGlobalSection 42 + GlobalSection(SolutionProperties) = preSolution 43 + HideSolutionNode = FALSE 44 + EndGlobalSection 45 + EndGlobal
+149
src/external/jnipp/jnipp.vcxproj
··· 1 + <?xml version="1.0" encoding="utf-8"?> 2 + <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3 + <ItemGroup Label="ProjectConfigurations"> 4 + <ProjectConfiguration Include="Debug|Win32"> 5 + <Configuration>Debug</Configuration> 6 + <Platform>Win32</Platform> 7 + </ProjectConfiguration> 8 + <ProjectConfiguration Include="Release|Win32"> 9 + <Configuration>Release</Configuration> 10 + <Platform>Win32</Platform> 11 + </ProjectConfiguration> 12 + <ProjectConfiguration Include="Debug|x64"> 13 + <Configuration>Debug</Configuration> 14 + <Platform>x64</Platform> 15 + </ProjectConfiguration> 16 + <ProjectConfiguration Include="Release|x64"> 17 + <Configuration>Release</Configuration> 18 + <Platform>x64</Platform> 19 + </ProjectConfiguration> 20 + </ItemGroup> 21 + <PropertyGroup Label="Globals"> 22 + <ProjectGuid>{A32D4B7D-7009-4C87-9DE8-D7DB659F5B58}</ProjectGuid> 23 + <RootNamespace>jnipp</RootNamespace> 24 + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> 25 + </PropertyGroup> 26 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> 27 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> 28 + <ConfigurationType>StaticLibrary</ConfigurationType> 29 + <UseDebugLibraries>true</UseDebugLibraries> 30 + <PlatformToolset>v142</PlatformToolset> 31 + <CharacterSet>MultiByte</CharacterSet> 32 + </PropertyGroup> 33 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> 34 + <ConfigurationType>StaticLibrary</ConfigurationType> 35 + <UseDebugLibraries>false</UseDebugLibraries> 36 + <PlatformToolset>v142</PlatformToolset> 37 + <WholeProgramOptimization>true</WholeProgramOptimization> 38 + <CharacterSet>MultiByte</CharacterSet> 39 + </PropertyGroup> 40 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> 41 + <ConfigurationType>StaticLibrary</ConfigurationType> 42 + <UseDebugLibraries>true</UseDebugLibraries> 43 + <PlatformToolset>v142</PlatformToolset> 44 + <CharacterSet>MultiByte</CharacterSet> 45 + </PropertyGroup> 46 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> 47 + <ConfigurationType>StaticLibrary</ConfigurationType> 48 + <UseDebugLibraries>false</UseDebugLibraries> 49 + <PlatformToolset>v142</PlatformToolset> 50 + <WholeProgramOptimization>true</WholeProgramOptimization> 51 + <CharacterSet>MultiByte</CharacterSet> 52 + </PropertyGroup> 53 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 54 + <ImportGroup Label="ExtensionSettings"> 55 + </ImportGroup> 56 + <ImportGroup Label="Shared"> 57 + </ImportGroup> 58 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 59 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 60 + </ImportGroup> 61 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 62 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 63 + </ImportGroup> 64 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> 65 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 66 + </ImportGroup> 67 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> 68 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 69 + </ImportGroup> 70 + <PropertyGroup Label="UserMacros" /> 71 + <PropertyGroup /> 72 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 73 + <ClCompile> 74 + <WarningLevel>Level3</WarningLevel> 75 + <Optimization>Disabled</Optimization> 76 + <SDLCheck>true</SDLCheck> 77 + <AdditionalIncludeDirectories>$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32</AdditionalIncludeDirectories> 78 + </ClCompile> 79 + <Lib> 80 + <AdditionalDependencies>jvm.lib</AdditionalDependencies> 81 + </Lib> 82 + <Lib> 83 + <AdditionalLibraryDirectories>$(JAVA_HOME)\lib</AdditionalLibraryDirectories> 84 + </Lib> 85 + </ItemDefinitionGroup> 86 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> 87 + <ClCompile> 88 + <WarningLevel>Level3</WarningLevel> 89 + <Optimization>Disabled</Optimization> 90 + <SDLCheck>true</SDLCheck> 91 + <AdditionalIncludeDirectories>$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32</AdditionalIncludeDirectories> 92 + </ClCompile> 93 + <Lib> 94 + <AdditionalDependencies>jvm.lib</AdditionalDependencies> 95 + </Lib> 96 + <Lib> 97 + <AdditionalLibraryDirectories>$(JAVA_HOME)\lib</AdditionalLibraryDirectories> 98 + </Lib> 99 + </ItemDefinitionGroup> 100 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 101 + <ClCompile> 102 + <WarningLevel>Level3</WarningLevel> 103 + <Optimization>MaxSpeed</Optimization> 104 + <FunctionLevelLinking>true</FunctionLevelLinking> 105 + <IntrinsicFunctions>true</IntrinsicFunctions> 106 + <SDLCheck>true</SDLCheck> 107 + <AdditionalIncludeDirectories>$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32</AdditionalIncludeDirectories> 108 + </ClCompile> 109 + <Link> 110 + <EnableCOMDATFolding>true</EnableCOMDATFolding> 111 + <OptimizeReferences>true</OptimizeReferences> 112 + </Link> 113 + <Lib> 114 + <AdditionalDependencies>jvm.lib</AdditionalDependencies> 115 + </Lib> 116 + <Lib> 117 + <AdditionalLibraryDirectories>$(JAVA_HOME)\lib</AdditionalLibraryDirectories> 118 + </Lib> 119 + </ItemDefinitionGroup> 120 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> 121 + <ClCompile> 122 + <WarningLevel>Level3</WarningLevel> 123 + <Optimization>MaxSpeed</Optimization> 124 + <FunctionLevelLinking>true</FunctionLevelLinking> 125 + <IntrinsicFunctions>true</IntrinsicFunctions> 126 + <SDLCheck>true</SDLCheck> 127 + <AdditionalIncludeDirectories>$(JAVA_HOME)\include;$(JAVA_HOME)\include\win32</AdditionalIncludeDirectories> 128 + </ClCompile> 129 + <Link> 130 + <EnableCOMDATFolding>true</EnableCOMDATFolding> 131 + <OptimizeReferences>true</OptimizeReferences> 132 + </Link> 133 + <Lib> 134 + <AdditionalDependencies>jvm.lib</AdditionalDependencies> 135 + </Lib> 136 + <Lib> 137 + <AdditionalLibraryDirectories>$(JAVA_HOME)\lib</AdditionalLibraryDirectories> 138 + </Lib> 139 + </ItemDefinitionGroup> 140 + <ItemGroup> 141 + <ClInclude Include="jnipp.h" /> 142 + </ItemGroup> 143 + <ItemGroup> 144 + <ClCompile Include="jnipp.cpp" /> 145 + </ItemGroup> 146 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 147 + <ImportGroup Label="ExtensionTargets"> 148 + </ImportGroup> 149 + </Project>
+9
src/external/jnipp/jnipp.vcxproj.filters
··· 1 + <?xml version="1.0" encoding="utf-8"?> 2 + <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3 + <ItemGroup> 4 + <ClInclude Include="jnipp.h" /> 5 + </ItemGroup> 6 + <ItemGroup> 7 + <ClCompile Include="jnipp.cpp" /> 8 + </ItemGroup> 9 + </Project>
+32
src/external/jnipp/makefile
··· 1 + CC=g++ 2 + 3 + OS_NAME := linux 4 + 5 + ifeq ($(OS),Windows_NT) 6 + OS_NAME := win32 7 + RM := del 8 + else 9 + RM := rm -f 10 + UNAME_S := $(shell uname -s) 11 + ifeq ($(UNAME_S),Darwin) 12 + OS_NAME := darwin 13 + endif 14 + endif 15 + 16 + JAVA_HOME ?= /usr/lib/jvm/default-java 17 + 18 + CXXFLAGS=-I. -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(OS_NAME) -ldl -std=c++11 19 + 20 + SRC=jnipp.o main.o 21 + VPATH=tests 22 + 23 + %.o: %.cpp 24 + $(CC) -c -o $@ $< $(CXXFLAGS) 25 + 26 + test: $(SRC) 27 + $(CC) -o test $(SRC) $(CXXFLAGS) 28 + 29 + clean: 30 + -$(RM) $(SRC) test 31 + 32 + .PHONY: clean
+619
src/external/jnipp/tests/main.cpp
··· 1 + // Project Dependencies 2 + #include <jnipp.h> 3 + 4 + // Standard Dependencies 5 + #include <cmath> 6 + 7 + // Local Dependencies 8 + #include "testing.h" 9 + 10 + /* 11 + jni::Vm Tests 12 + */ 13 + 14 + 15 + TEST(Vm_detectsJreInstall) 16 + { 17 + try 18 + { 19 + jni::Vm vm; 20 + } 21 + catch (jni::InitializationException&) 22 + { 23 + ASSERT(0); 24 + return; 25 + } 26 + 27 + ASSERT(1); 28 + } 29 + 30 + TEST(Vm_notAllowedMultipleVms) 31 + { 32 + try 33 + { 34 + jni::Vm firstVm; 35 + jni::Vm secondVm; // Throws an exception. 36 + } 37 + catch (jni::InitializationException&) 38 + { 39 + ASSERT(1); 40 + return; 41 + } 42 + 43 + ASSERT(0); 44 + } 45 + 46 + /* 47 + jni::Class Tests 48 + */ 49 + 50 + 51 + TEST(Class_findByName_success) 52 + { 53 + jni::Class cls("java/lang/String"); 54 + 55 + ASSERT(!cls.isNull()); 56 + } 57 + 58 + TEST(Class_findByName_failure) 59 + { 60 + try 61 + { 62 + jni::Class cls("does/not/Exist"); 63 + } 64 + catch (jni::NameResolutionException&) 65 + { 66 + ASSERT(1); 67 + return; 68 + } 69 + 70 + ASSERT(0); 71 + } 72 + 73 + TEST(Class_getName) 74 + { 75 + jni::Class cls("java/lang/String"); 76 + 77 + ASSERT(cls.getName() == "java.lang.String"); 78 + } 79 + 80 + TEST(Class_getParent) 81 + { 82 + jni::Class parent = jni::Class("java/lang/Integer").getParent(); 83 + 84 + ASSERT(parent.getName() == "java.lang.Number"); 85 + } 86 + 87 + TEST(Class_newInstance) 88 + { 89 + jni::Class Integer("java/lang/Integer"); 90 + jni::method_t constructor = Integer.getConstructor("(Ljava/lang/String;)V"); 91 + jni::Object i = Integer.newInstance(constructor, "123"); 92 + jni::Object str = jni::Class("java/lang/String").newInstance(); 93 + 94 + ASSERT(!i.isNull()); 95 + ASSERT(!str.isNull()); 96 + } 97 + 98 + TEST(Class_newInstance_withArgs) 99 + { 100 + jni::Object str1 = jni::Class("java/lang/String").newInstance("Testing..."); 101 + jni::Object str2 = jni::Class("java/lang/String").newInstance(L"Testing..."); 102 + 103 + ASSERT(!str1.isNull()); 104 + ASSERT(!str2.isNull()); 105 + } 106 + 107 + TEST(Class_getStaticField) 108 + { 109 + jni::field_t field = jni::Class("java/lang/Integer").getStaticField("MAX_VALUE", "I"); 110 + 111 + ASSERT(field); 112 + } 113 + 114 + TEST(Class_getMethod) 115 + { 116 + jni::method_t method1 = jni::Class("java/lang/Integer").getMethod("intValue", "()I"); 117 + jni::method_t method2 = jni::Class("java/lang/Integer").getMethod("intValue()I"); 118 + 119 + ASSERT(method1); 120 + ASSERT(method2); 121 + } 122 + 123 + TEST(Class_getStaticMethod) 124 + { 125 + jni::method_t method = jni::Class("java/lang/Integer").getStaticMethod("compare", "(II)I"); 126 + 127 + ASSERT(method); 128 + } 129 + 130 + TEST(Class_call) 131 + { 132 + jni::Class Integer("java/lang/Math"); 133 + 134 + double x = Integer.call<double>("random"); 135 + 136 + ASSERT(x >= 0.0); 137 + ASSERT(x < 1.0); 138 + } 139 + 140 + TEST(Class_get_staticField) 141 + { 142 + jni::Class Integer("java/lang/Integer"); 143 + jni::field_t field = Integer.getStaticField("SIZE", "I"); 144 + 145 + ASSERT(Integer.get<int>(field) == 32); 146 + } 147 + 148 + TEST(Class_get_staticField_byName) 149 + { 150 + jni::Class Integer("java/lang/Integer"); 151 + jni::Class Character("java/lang/Character"); 152 + jni::Class Short("java/lang/Short"); 153 + jni::Class Long("java/lang/Long"); 154 + jni::Class Float("java/lang/Float"); 155 + jni::Class Double("java/lang/Double"); 156 + 157 + ASSERT(Short.get<short>("MAX_VALUE") == short(0x7FFF)); 158 + ASSERT(Character.get<wchar_t>("MAX_VALUE") == L'\xFFFF') 159 + ASSERT(Integer.get<int>("MAX_VALUE") == int(0x7FFFFFFF)); 160 + ASSERT(Long.get<long long>("MAX_VALUE") == (long long) (0x7FFFFFFFFFFFFFFF)); 161 + ASSERT(std::isnan(Float.get<float>("NaN"))); 162 + ASSERT(std::isnan(Double.get<double>("NaN"))); 163 + } 164 + 165 + TEST(Class_getConstructor) 166 + { 167 + jni::Class Integer("java/lang/Integer"); 168 + jni::method_t constructor = Integer.getConstructor("(Ljava/lang/String;)V"); 169 + 170 + ASSERT(constructor); 171 + } 172 + 173 + TEST(Class_call_staticMethod) 174 + { 175 + jni::Class Integer("java/lang/Integer"); 176 + jni::method_t method = Integer.getStaticMethod("parseInt", "(Ljava/lang/String;)I"); 177 + 178 + int i = Integer.call<int>(method, "1000"); 179 + 180 + ASSERT(i == 1000); 181 + } 182 + 183 + TEST(Class_call_staticMethod_byName) 184 + { 185 + int i = jni::Class("java/lang/Integer").call<int>("parseInt", "1000"); 186 + bool b = jni::Class("java/lang/Boolean").call<bool>("parseBoolean", "true"); 187 + wchar_t c = jni::Class("java/lang/Character").call<wchar_t>("toLowerCase", L'X'); 188 + short s = jni::Class("java/lang/Short").call<short>("parseShort", "1000"); 189 + long long l = jni::Class("java/lang/Long").call<long long>("parseLong", "1000"); 190 + float f = jni::Class("java/lang/Float").call<float>("parseFloat", "123.0"); 191 + double d = jni::Class("java/lang/Double").call<double>("parseDouble", "123.0"); 192 + 193 + ASSERT(i == 1000); 194 + ASSERT(b == true); 195 + ASSERT(c == L'x'); 196 + ASSERT(s == 1000); 197 + ASSERT(l == 1000); 198 + ASSERT(f == 123.0); // Warning: floating point comparison. 199 + ASSERT(d == 123.0); // Warning: floating point comparison. 200 + } 201 + 202 + /* 203 + jni::Object Tests 204 + */ 205 + 206 + 207 + TEST(Object_defaultConstructor_isNull) 208 + { 209 + jni::Object o; 210 + 211 + ASSERT(o.isNull()); 212 + } 213 + 214 + TEST(Object_copyConstructorIsSameObject) 215 + { 216 + jni::Object a = jni::Class("java/lang/String").newInstance(); 217 + jni::Object b = a; 218 + 219 + ASSERT(a == b); 220 + } 221 + 222 + TEST(Object_moveConstructor) 223 + { 224 + jni::Object a = jni::Class("java/lang/String").newInstance(); 225 + jni::Object b = std::move(a); 226 + 227 + ASSERT(a.isNull()); 228 + ASSERT(!b.isNull()); 229 + } 230 + 231 + TEST(Object_copyAssignmentOperator) 232 + { 233 + jni::Object a = jni::Class("java/lang/String").newInstance(); 234 + jni::Object b = jni::Class("java/lang/Integer").newInstance(0); 235 + 236 + a = b; 237 + 238 + ASSERT(a == b); 239 + } 240 + 241 + TEST(Object_moveAssignmentOperator) 242 + { 243 + jni::Object a = jni::Class("java/lang/String").newInstance(); 244 + jni::Object b = jni::Class("java/lang/Integer").newInstance(0); 245 + 246 + a = std::move(b); 247 + 248 + ASSERT(!a.isNull()); 249 + ASSERT(b.isNull()); 250 + } 251 + 252 + TEST(Object_call) 253 + { 254 + jni::Class Integer("java/lang/Integer"); 255 + jni::method_t intValue = Integer.getMethod("intValue", "()I"); 256 + jni::Object i = Integer.newInstance(100); 257 + 258 + ASSERT(i.call<int>(intValue) == 100); 259 + } 260 + 261 + TEST(Object_call_byName) 262 + { 263 + jni::Object i = jni::Class("java/lang/Integer").newInstance(100); 264 + jni::Object b = jni::Class("java/lang/Boolean").newInstance(true); 265 + jni::Object s = jni::Class("java/lang/Short").newInstance(short(100)); 266 + jni::Object l = jni::Class("java/lang/Long").newInstance(100LL); 267 + jni::Object f = jni::Class("java/lang/Float").newInstance(100.0f); 268 + jni::Object d = jni::Class("java/lang/Double").newInstance(100.0); 269 + 270 + ASSERT(i.call<int>("intValue") == 100); 271 + ASSERT(s.call<short>("shortValue") == 100); 272 + ASSERT(b.call<bool>("booleanValue") == true); 273 + ASSERT(l.call<long long>("longValue") == 100LL); 274 + ASSERT(f.call<float>("floatValue") == 100.0f); // Warning: Floating point comparison. 275 + ASSERT(d.call<double>("doubleValue") == 100.0); // Warning: Floating point comparison. 276 + ASSERT(i.call<std::wstring>("toString") == L"100"); 277 + ASSERT(i.call<std::string>("toString") == "100"); 278 + } 279 + 280 + TEST(Object_call_withArgs) 281 + { 282 + jni::Class String("java/lang/String"); 283 + jni::method_t charAt = String.getMethod("charAt", "(I)C"); 284 + jni::Object str = String.newInstance("Testing"); 285 + 286 + ASSERT(str.call<wchar_t>(charAt, 1) == L'e'); 287 + } 288 + 289 + TEST(Object_call_byNameWithArgs) 290 + { 291 + jni::Object str = jni::Class("java/lang/String").newInstance("Testing"); 292 + jni::Object str2 = jni::Class("java/lang/String").newInstance(L"Testing"); 293 + 294 + ASSERT(str.call<wchar_t>("charAt", 1) == L'e'); 295 + ASSERT(str2.call<wchar_t>("charAt", 1) == L'e'); 296 + } 297 + 298 + TEST(Object_makeLocalReference) 299 + { 300 + jni::Object str = jni::Class("java/lang/String").newInstance("Testing"); 301 + 302 + jni::jobject local = str.makeLocalReference(); 303 + ASSERT(local != nullptr); 304 + ASSERT(local != str.getHandle()); 305 + 306 + jni::Object fromLocal(local, jni::Object::DeleteLocalInput); 307 + ASSERT(!fromLocal.isNull()); 308 + ASSERT(str == fromLocal); 309 + } 310 + 311 + /* 312 + jni::Enum Tests 313 + */ 314 + 315 + 316 + TEST(Enum_get) 317 + { 318 + jni::Class Thread("java/lang/Thread"); 319 + jni::Enum State("java/lang/Thread$State"); 320 + jni::method_t currentThread = Thread.getStaticMethod("currentThread", "()Ljava/lang/Thread;"); 321 + jni::method_t getState = Thread.getMethod("getState", "()Ljava/lang/Thread$State;"); 322 + 323 + jni::Object thread = Thread.call<jni::Object>(currentThread); 324 + jni::Object state = thread.call<jni::Object>(getState); 325 + 326 + ASSERT(state == State.get("RUNNABLE")); 327 + } 328 + 329 + /* 330 + jni::Array Tests 331 + */ 332 + 333 + TEST(Array_defaultConstructor) 334 + { 335 + jni::Array<int> a; 336 + 337 + ASSERT(a.getLength() == 0); 338 + ASSERT(a.isNull()); 339 + } 340 + 341 + TEST(Array_constructor) 342 + { 343 + jni::Array<int> a(10); 344 + 345 + ASSERT(a.getLength() == 10); 346 + ASSERT(!a.isNull()); 347 + } 348 + 349 + TEST(Array_constructor_eachType) 350 + { 351 + jni::Array<bool> b(10); 352 + jni::Array<wchar_t> c(10); 353 + jni::Array<short> s(10); 354 + jni::Array<int> i(10); 355 + jni::Array<long long> l(10); 356 + jni::Array<float> f(10); 357 + jni::Array<double> d(10); 358 + jni::Array<std::string> str(10); 359 + jni::Array<std::wstring> wstr(10); 360 + jni::Array<jni::Object> obj(10); 361 + jni::Array<jni::Object> obj2(10, jni::Class("java/lang/Integer")); 362 + 363 + jni::Object* objs[] = { &b, &c, &s, &i, &l, &f, &d, &str, &wstr, &obj, &obj2 }; 364 + 365 + for (auto o : objs) 366 + ASSERT(!o->isNull()); 367 + } 368 + 369 + TEST(Array_constructor_withType) 370 + { 371 + jni::Array<jni::Object> a(10, jni::Class("java/lang/Integer")); 372 + 373 + ASSERT(a.getLength() == 10); 374 + ASSERT(!a.isNull()); 375 + } 376 + 377 + TEST(Array_copyConstructor) 378 + { 379 + jni::Array<int> a(10); 380 + jni::Array<int> b = a; 381 + 382 + ASSERT(a == b); 383 + } 384 + 385 + TEST(Array_moveConstructor) 386 + { 387 + jni::Array<int> a(10); 388 + jni::Array<int> b = std::move(a); 389 + 390 + ASSERT(a.isNull()); 391 + ASSERT(!b.isNull()); 392 + } 393 + 394 + TEST(Array_copyAssignmentOperator) 395 + { 396 + jni::Array<int> a(10); 397 + jni::Array<int> b(11); 398 + 399 + a = b; 400 + 401 + ASSERT(a == b); 402 + } 403 + 404 + TEST(Array_moveAssignmentOperator) 405 + { 406 + jni::Array<int> a(10); 407 + jni::Array<int> b(11); 408 + 409 + a = std::move(b); 410 + 411 + ASSERT(!a.isNull()); 412 + ASSERT(b.isNull()); 413 + } 414 + 415 + TEST(Array_getElement_defaultValue) 416 + { 417 + jni::Array<int> a(10); 418 + jni::Array<std::string> s(10); 419 + 420 + ASSERT(a.getElement(0) == 0); 421 + ASSERT(s.getElement(0).length() == 0); 422 + } 423 + 424 + TEST(Array_getElement_indexException) 425 + { 426 + jni::Array<int> a(10); 427 + 428 + try 429 + { 430 + int result = a.getElement(1000); 431 + ASSERT(0); 432 + } 433 + catch (jni::Exception&) 434 + { 435 + ASSERT(1); 436 + } 437 + } 438 + 439 + TEST(Array_setElement_basicType) 440 + { 441 + jni::Array<int> a(10); 442 + 443 + for (int i = 0; i < 10; i++) 444 + a.setElement(i, i); 445 + 446 + for (int i = 0; i < 10; i++) 447 + ASSERT(a.getElement(i) == i); 448 + } 449 + 450 + TEST(Array_setElement_string) 451 + { 452 + jni::Array<std::wstring> a(10); 453 + 454 + for (int i = 0; i < 10; i++) 455 + a.setElement(i, std::to_wstring(i)); 456 + 457 + for (int i = 0; i < 10; i++) 458 + ASSERT(a.getElement(i) == std::to_wstring(i)); 459 + } 460 + 461 + TEST(Array_setElement_indexException) 462 + { 463 + jni::Array<std::string> s(10); 464 + 465 + try 466 + { 467 + auto result = s.getElement(1000); 468 + ASSERT(0); 469 + } 470 + catch (jni::Exception&) 471 + { 472 + ASSERT(1); 473 + } 474 + } 475 + 476 + /* 477 + Argument Type Tests 478 + */ 479 + 480 + 481 + TEST(Arg_bool) 482 + { 483 + std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", true); 484 + std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", true); 485 + 486 + ASSERT(str1 == "true"); 487 + ASSERT(str2 == L"true"); 488 + } 489 + 490 + TEST(Arg_wchar) 491 + { 492 + std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", L'X'); 493 + std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", L'X'); 494 + 495 + ASSERT(str1 == "X"); 496 + ASSERT(str2 == L"X"); 497 + } 498 + 499 + TEST(Arg_double) 500 + { 501 + std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", 123.0); 502 + std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", 123.0); 503 + 504 + ASSERT(str1 == "123.0"); 505 + ASSERT(str2 == L"123.0"); 506 + } 507 + 508 + TEST(Arg_float) 509 + { 510 + std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", 123.0f); 511 + std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", 123.0f); 512 + 513 + ASSERT(str1 == "123.0"); 514 + ASSERT(str2 == L"123.0"); 515 + } 516 + 517 + TEST(Arg_int) 518 + { 519 + std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", 123); 520 + std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", 123); 521 + 522 + ASSERT(str1 == "123"); 523 + ASSERT(str2 == L"123"); 524 + } 525 + 526 + TEST(Arg_longLong) 527 + { 528 + std::string str1 = jni::Class("java/lang/String").call<std::string>("valueOf", 123LL); 529 + std::wstring str2 = jni::Class("java/lang/String").call<std::wstring>("valueOf", 123LL); 530 + 531 + ASSERT(str1 == "123"); 532 + ASSERT(str2 == L"123"); 533 + } 534 + 535 + TEST(Arg_Object) 536 + { 537 + jni::Object str1 = jni::Class("java/lang/String").newInstance("123"); 538 + int i = jni::Class("java/lang/Integer").call<int>("parseInt", str1); 539 + 540 + ASSERT(i == 123); 541 + } 542 + 543 + TEST(Arg_ObjectPtr) 544 + { 545 + jni::Object str1 = jni::Class("java/lang/String").newInstance("123"); 546 + int i = jni::Class("java/lang/Integer").call<int>("parseInt", &str1); 547 + 548 + ASSERT(i == 123); 549 + } 550 + 551 + int main() 552 + { 553 + // jni::Vm Tests 554 + RUN_TEST(Vm_detectsJreInstall); 555 + RUN_TEST(Vm_notAllowedMultipleVms); 556 + 557 + { 558 + jni::Vm vm; 559 + 560 + // jni::Class Tests 561 + RUN_TEST(Class_findByName_success); 562 + RUN_TEST(Class_findByName_failure); 563 + RUN_TEST(Class_getName); 564 + RUN_TEST(Class_getParent); 565 + RUN_TEST(Class_newInstance); 566 + RUN_TEST(Class_newInstance_withArgs); 567 + RUN_TEST(Class_getStaticField); 568 + RUN_TEST(Class_getMethod); 569 + RUN_TEST(Class_getStaticMethod); 570 + RUN_TEST(Class_call); 571 + RUN_TEST(Class_get_staticField); 572 + RUN_TEST(Class_get_staticField_byName); 573 + RUN_TEST(Class_call_staticMethod_byName); 574 + RUN_TEST(Class_getConstructor); 575 + 576 + // jni::Object Tests 577 + RUN_TEST(Object_defaultConstructor_isNull); 578 + RUN_TEST(Object_copyConstructorIsSameObject); 579 + RUN_TEST(Object_moveConstructor); 580 + RUN_TEST(Object_copyAssignmentOperator); 581 + RUN_TEST(Object_moveAssignmentOperator); 582 + RUN_TEST(Object_call); 583 + RUN_TEST(Object_call_byName); 584 + RUN_TEST(Object_call_withArgs); 585 + RUN_TEST(Object_call_byNameWithArgs); 586 + RUN_TEST(Object_makeLocalReference); 587 + 588 + // jni::Enum Tests 589 + RUN_TEST(Enum_get); 590 + 591 + // jni::Array Tests 592 + RUN_TEST(Array_defaultConstructor); 593 + RUN_TEST(Array_constructor); 594 + RUN_TEST(Array_constructor_eachType); 595 + RUN_TEST(Array_constructor_withType); 596 + RUN_TEST(Array_copyConstructor); 597 + RUN_TEST(Array_moveConstructor); 598 + RUN_TEST(Array_getElement_defaultValue); 599 + RUN_TEST(Array_getElement_indexException); 600 + RUN_TEST(Array_setElement_basicType); 601 + RUN_TEST(Array_setElement_string); 602 + RUN_TEST(Array_setElement_indexException); 603 + 604 + // Argument Type Tests 605 + RUN_TEST(Arg_bool); 606 + RUN_TEST(Arg_wchar); 607 + RUN_TEST(Arg_double); 608 + RUN_TEST(Arg_float); 609 + RUN_TEST(Arg_int); 610 + RUN_TEST(Arg_longLong); 611 + RUN_TEST(Arg_Object); 612 + RUN_TEST(Arg_ObjectPtr); 613 + } 614 + 615 + std::cout << "Press a key to continue..." << std::endl; 616 + std::cin.get(); 617 + return 0; 618 + } 619 +
+33
src/external/jnipp/tests/testing.h
··· 1 + #ifndef _TESTING_H_ 2 + #define _TESTING_H_ 1 3 + 4 + // Standard Dependencies 5 + #include <iostream> 6 + #include <iomanip> 7 + 8 + #ifdef ASSERT 9 + # undef ASSERT 10 + #endif 11 + 12 + /** Run the test with the given name. */ 13 + #define RUN_TEST(TestName) { \ 14 + bool __test_result = true; \ 15 + std::cout << "Executing test " << std::left << std::setw(40) << #TestName; \ 16 + TestName(__test_result); \ 17 + std::cout << "=> " << (__test_result ? "Success" : "Fail") << std::endl; \ 18 + } 19 + 20 + /** Define a test with the given name. */ 21 + #define TEST(TestName) \ 22 + void TestName(bool& __test_result) 23 + 24 + /** Ensures the given condition passes for the test to pass. */ 25 + #define ASSERT(condition) { \ 26 + if (!(condition)) { \ 27 + __test_result = false; \ 28 + return; \ 29 + } \ 30 + } 31 + 32 + #endif // _TESTING_H_ 33 +
+130
src/external/jnipp/tests/tests.vcxproj
··· 1 + <?xml version="1.0" encoding="utf-8"?> 2 + <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3 + <ItemGroup Label="ProjectConfigurations"> 4 + <ProjectConfiguration Include="Debug|Win32"> 5 + <Configuration>Debug</Configuration> 6 + <Platform>Win32</Platform> 7 + </ProjectConfiguration> 8 + <ProjectConfiguration Include="Release|Win32"> 9 + <Configuration>Release</Configuration> 10 + <Platform>Win32</Platform> 11 + </ProjectConfiguration> 12 + <ProjectConfiguration Include="Debug|x64"> 13 + <Configuration>Debug</Configuration> 14 + <Platform>x64</Platform> 15 + </ProjectConfiguration> 16 + <ProjectConfiguration Include="Release|x64"> 17 + <Configuration>Release</Configuration> 18 + <Platform>x64</Platform> 19 + </ProjectConfiguration> 20 + </ItemGroup> 21 + <PropertyGroup Label="Globals"> 22 + <ProjectGuid>{911DB449-3D76-4261-8FFD-9BA508ED1D5B}</ProjectGuid> 23 + <RootNamespace>tests</RootNamespace> 24 + <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> 25 + </PropertyGroup> 26 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> 27 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> 28 + <ConfigurationType>Application</ConfigurationType> 29 + <UseDebugLibraries>true</UseDebugLibraries> 30 + <PlatformToolset>v142</PlatformToolset> 31 + <CharacterSet>MultiByte</CharacterSet> 32 + </PropertyGroup> 33 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> 34 + <ConfigurationType>Application</ConfigurationType> 35 + <UseDebugLibraries>false</UseDebugLibraries> 36 + <PlatformToolset>v142</PlatformToolset> 37 + <WholeProgramOptimization>true</WholeProgramOptimization> 38 + <CharacterSet>MultiByte</CharacterSet> 39 + </PropertyGroup> 40 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> 41 + <ConfigurationType>Application</ConfigurationType> 42 + <UseDebugLibraries>true</UseDebugLibraries> 43 + <PlatformToolset>v142</PlatformToolset> 44 + <CharacterSet>MultiByte</CharacterSet> 45 + </PropertyGroup> 46 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> 47 + <ConfigurationType>Application</ConfigurationType> 48 + <UseDebugLibraries>false</UseDebugLibraries> 49 + <PlatformToolset>v142</PlatformToolset> 50 + <WholeProgramOptimization>true</WholeProgramOptimization> 51 + <CharacterSet>MultiByte</CharacterSet> 52 + </PropertyGroup> 53 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 54 + <ImportGroup Label="ExtensionSettings"> 55 + </ImportGroup> 56 + <ImportGroup Label="Shared"> 57 + </ImportGroup> 58 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 59 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 60 + </ImportGroup> 61 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 62 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 63 + </ImportGroup> 64 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> 65 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 66 + </ImportGroup> 67 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> 68 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 69 + </ImportGroup> 70 + <PropertyGroup Label="UserMacros" /> 71 + <PropertyGroup /> 72 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 73 + <ClCompile> 74 + <WarningLevel>Level3</WarningLevel> 75 + <Optimization>Disabled</Optimization> 76 + <SDLCheck>true</SDLCheck> 77 + <AdditionalIncludeDirectories>$(SolutionDir)</AdditionalIncludeDirectories> 78 + </ClCompile> 79 + </ItemDefinitionGroup> 80 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> 81 + <ClCompile> 82 + <WarningLevel>Level3</WarningLevel> 83 + <Optimization>Disabled</Optimization> 84 + <SDLCheck>true</SDLCheck> 85 + <AdditionalIncludeDirectories>$(SolutionDir)</AdditionalIncludeDirectories> 86 + </ClCompile> 87 + </ItemDefinitionGroup> 88 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 89 + <ClCompile> 90 + <WarningLevel>Level3</WarningLevel> 91 + <Optimization>MaxSpeed</Optimization> 92 + <FunctionLevelLinking>true</FunctionLevelLinking> 93 + <IntrinsicFunctions>true</IntrinsicFunctions> 94 + <SDLCheck>true</SDLCheck> 95 + <AdditionalIncludeDirectories>$(SolutionDir)</AdditionalIncludeDirectories> 96 + </ClCompile> 97 + <Link> 98 + <EnableCOMDATFolding>true</EnableCOMDATFolding> 99 + <OptimizeReferences>true</OptimizeReferences> 100 + </Link> 101 + </ItemDefinitionGroup> 102 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> 103 + <ClCompile> 104 + <WarningLevel>Level3</WarningLevel> 105 + <Optimization>MaxSpeed</Optimization> 106 + <FunctionLevelLinking>true</FunctionLevelLinking> 107 + <IntrinsicFunctions>true</IntrinsicFunctions> 108 + <SDLCheck>true</SDLCheck> 109 + <AdditionalIncludeDirectories>$(SolutionDir)</AdditionalIncludeDirectories> 110 + </ClCompile> 111 + <Link> 112 + <EnableCOMDATFolding>true</EnableCOMDATFolding> 113 + <OptimizeReferences>true</OptimizeReferences> 114 + </Link> 115 + </ItemDefinitionGroup> 116 + <ItemGroup> 117 + <ProjectReference Include="..\jnipp.vcxproj"> 118 + <Project>{a32d4b7d-7009-4c87-9de8-d7db659f5b58}</Project> 119 + </ProjectReference> 120 + </ItemGroup> 121 + <ItemGroup> 122 + <ClCompile Include="main.cpp" /> 123 + </ItemGroup> 124 + <ItemGroup> 125 + <ClInclude Include="testing.h" /> 126 + </ItemGroup> 127 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 128 + <ImportGroup Label="ExtensionTargets"> 129 + </ImportGroup> 130 + </Project>
+9
src/external/jnipp/tests/tests.vcxproj.filters
··· 1 + <?xml version="1.0" encoding="utf-8"?> 2 + <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3 + <ItemGroup> 4 + <ClCompile Include="main.cpp" /> 5 + </ItemGroup> 6 + <ItemGroup> 7 + <ClInclude Include="testing.h" /> 8 + </ItemGroup> 9 + </Project>