ikvm-fork/runtime/JniInterface.cs

3415 строки
116 KiB
C#
Исходник Обычный вид История

2003-01-07 14:40:11 +03:00
/*
Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Jeroen Frijters
2003-01-07 14:40:11 +03:00
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jeroen Frijters
jeroen@frijters.net
*/
2005-12-07 12:06:32 +03:00
#if !COMPACT_FRAMEWORK
2003-01-07 14:40:11 +03:00
using System;
2004-08-30 19:56:23 +04:00
using System.Collections;
2004-09-15 17:35:44 +04:00
using System.Collections.Specialized;
2004-08-17 13:05:21 +04:00
using System.Diagnostics;
2003-01-17 17:34:33 +03:00
using System.Text;
2003-01-07 14:40:11 +03:00
using System.Reflection;
2003-01-17 17:34:33 +03:00
using System.Runtime.InteropServices;
2004-09-09 15:17:55 +04:00
using IKVM.Internal;
2003-01-07 14:40:11 +03:00
2004-09-05 13:37:58 +04:00
// Java type JNI aliases
using jboolean = System.SByte;
using jbyte = System.SByte;
using jchar = System.UInt16;
using jshort = System.Int16;
using jint = System.Int32;
using jsize = System.Int32;
using jlong = System.Int64;
using jfloat = System.Single;
using jdouble = System.Double;
using jobject = System.IntPtr;
using jstring = System.IntPtr;
using jclass = System.IntPtr;
using jarray = System.IntPtr;
using jobjectArray = System.IntPtr;
using jbooleanArray = System.IntPtr;
using jbyteArray = System.IntPtr;
using jcharArray = System.IntPtr;
using jshortArray = System.IntPtr;
using jintArray = System.IntPtr;
using jlongArray = System.IntPtr;
using jfloatArray = System.IntPtr;
using jdoubleArray = System.IntPtr;
using jthrowable = System.IntPtr;
using jweak = System.IntPtr;
using jmethodID = System.IntPtr;
using jfieldID = System.IntPtr;
2004-09-09 15:17:55 +04:00
namespace IKVM.Runtime
2003-01-07 14:40:11 +03:00
{
2004-09-09 15:17:55 +04:00
[StructLayout(LayoutKind.Sequential)]
unsafe struct JavaVMOption
{
internal byte* optionString;
2004-09-09 15:17:55 +04:00
internal void* extraInfo;
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct JavaVMInitArgs
{
internal jint version;
internal jint nOptions;
internal JavaVMOption* options;
internal jboolean ignoreUnrecognized;
}
public unsafe sealed class JNI
2003-01-07 14:40:11 +03:00
{
2005-02-23 15:56:15 +03:00
internal static volatile bool jvmCreated;
internal static volatile bool jvmDestroyed;
internal const string METHOD_PTR_FIELD_PREFIX = "__<jniptr>";
2004-09-09 15:17:55 +04:00
2005-02-02 18:11:26 +03:00
internal static bool IsSupportedJniVersion(jint version)
{
return version == JNIEnv.JNI_VERSION_1_1 || version == JNIEnv.JNI_VERSION_1_2 || version == JNIEnv.JNI_VERSION_1_4;
}
2004-09-09 15:17:55 +04:00
public static int CreateJavaVM(void* ppvm, void* ppenv, void* args)
2003-01-07 14:40:11 +03:00
{
2004-09-09 15:17:55 +04:00
JavaVMInitArgs* pInitArgs = (JavaVMInitArgs*)args;
// we don't support the JDK 1.1 JavaVMInitArgs
2005-02-02 18:11:26 +03:00
if(!IsSupportedJniVersion(pInitArgs->version) || pInitArgs->version == JNIEnv.JNI_VERSION_1_1)
2004-09-09 15:17:55 +04:00
{
return JNIEnv.JNI_EVERSION;
}
if(jvmCreated)
{
return JNIEnv.JNI_ERR;
}
2004-10-19 17:43:55 +04:00
Hashtable props = new Hashtable();
2004-09-09 15:17:55 +04:00
for(int i = 0; i < pInitArgs->nOptions; i++)
2003-01-17 17:34:33 +03:00
{
string option = JNIEnv.StringFromOEM(pInitArgs->options[i].optionString);
2004-09-09 15:17:55 +04:00
if(option.StartsWith("-D"))
{
int idx = option.IndexOf('=', 2);
props[option.Substring(2, idx - 2)] = option.Substring(idx + 1);
}
else if(option.StartsWith("-verbose"))
{
// ignore
}
else if(option == "vfprintf" || option == "exit" || option == "abort")
{
// not supported
}
else if(pInitArgs->ignoreUnrecognized == JNIEnv.JNI_FALSE)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
return JNIEnv.JNI_ERR;
2004-08-17 13:05:21 +04:00
}
2003-01-17 17:34:33 +03:00
}
2004-08-30 19:56:23 +04:00
2006-08-17 11:33:38 +04:00
JVM.Library.setProperties(props);
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
*((void**)ppvm) = JavaVM.pJavaVM;
return JavaVM.AttachCurrentThread(JavaVM.pJavaVM, (void**)ppenv, null);
}
public static int GetDefaultJavaVMInitArgs(void* vm_args)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
// This is only used for JDK 1.1 JavaVMInitArgs, and we don't support those.
return JNIEnv.JNI_ERR;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
public static int GetCreatedJavaVMs(void* ppvmBuf, int bufLen, int* nVMs)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(jvmCreated)
{
if(bufLen >= 1)
{
*((void**)ppvmBuf) = JavaVM.pJavaVM;
}
2005-06-28 11:12:28 +04:00
if(nVMs != null)
{
*nVMs = 1;
}
2004-09-09 15:17:55 +04:00
}
2005-06-28 11:12:28 +04:00
else if(nVMs != null)
2004-09-09 15:17:55 +04:00
{
*nVMs = 0;
}
return JNIEnv.JNI_OK;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
public unsafe struct Frame
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
private JNIEnv* pJNIEnv;
private RuntimeMethodHandle prevMethod;
private object[] quickLocals;
private int quickLocalIndex;
private int prevLocalRefSlot;
2005-01-05 15:56:37 +03:00
internal ClassLoaderWrapper Enter(ClassLoaderWrapper loader)
{
Enter(new RuntimeMethodHandle());
ClassLoaderWrapper prev = (ClassLoaderWrapper)pJNIEnv->classLoader.Target;
pJNIEnv->classLoader.Target = loader;
return prev;
}
internal void Leave(ClassLoaderWrapper prev)
{
pJNIEnv->classLoader.Target = prev;
2005-03-17 17:27:18 +03:00
Leave();
2005-01-05 15:56:37 +03:00
}
2004-09-09 15:17:55 +04:00
public IntPtr Enter(RuntimeMethodHandle method)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
pJNIEnv = TlsHack.pJNIEnv;
if(pJNIEnv == null)
{
pJNIEnv = JNIEnv.CreateJNIEnv();
}
prevMethod = pJNIEnv->currentMethod;
pJNIEnv->currentMethod = method;
object[][] localRefs = pJNIEnv->GetLocalRefs();
prevLocalRefSlot = pJNIEnv->localRefSlot;
pJNIEnv->localRefSlot++;
if(pJNIEnv->localRefSlot >= localRefs.Length)
{
object[][] tmp = new object[localRefs.Length * 2][];
Array.Copy(localRefs, 0, tmp, 0, localRefs.Length);
pJNIEnv->localRefs.Target = localRefs = tmp;
}
if(localRefs[pJNIEnv->localRefSlot] == null)
{
localRefs[pJNIEnv->localRefSlot] = new object[32];
}
quickLocals = localRefs[pJNIEnv->localRefSlot];
quickLocalIndex = (pJNIEnv->localRefSlot << JNIEnv.LOCAL_REF_SHIFT);
return (IntPtr)(void*)pJNIEnv;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
public void Leave()
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
pJNIEnv->currentMethod = prevMethod;
Exception x = (Exception)pJNIEnv->UnwrapRef(pJNIEnv->pendingException);
pJNIEnv->pendingException = IntPtr.Zero;
object[][] localRefs = pJNIEnv->GetLocalRefs();
while(pJNIEnv->localRefSlot != prevLocalRefSlot)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(localRefs[pJNIEnv->localRefSlot] != null)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(localRefs[pJNIEnv->localRefSlot].Length == JNIEnv.LOCAL_REF_BUCKET_SIZE)
{
// if the bucket is totally allocated, we're assuming a leaky method so we throw the bucket away
localRefs[pJNIEnv->localRefSlot] = null;
}
else
{
Array.Clear(localRefs[pJNIEnv->localRefSlot], 0, localRefs[pJNIEnv->localRefSlot].Length);
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
pJNIEnv->localRefSlot--;
}
if(x != null)
{
throw x;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
}
public static IntPtr GetFuncPtr(RuntimeMethodHandle method, string clazz, string name, string sig)
{
MethodBase mb = MethodBase.GetMethodFromHandle(method);
ClassLoaderWrapper loader = ClassLoaderWrapper.GetWrapperFromType(mb.DeclaringType).GetClassLoader();
int sp = 0;
for(int i = 1; sig[i] != ')'; i++)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
switch(sig[i])
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
case '[':
sp += IntPtr.Size;
2005-02-18 14:50:38 +03:00
while(sig[++i] == '[');
2004-09-09 15:17:55 +04:00
if(sig[i] == 'L')
{
2005-02-18 14:50:38 +03:00
while(sig[++i] != ';');
2004-09-09 15:17:55 +04:00
}
break;
case 'L':
sp += IntPtr.Size;
2005-02-18 14:50:38 +03:00
while(sig[++i] != ';');
2004-09-09 15:17:55 +04:00
break;
case 'J':
case 'D':
sp += 8;
break;
case 'F':
case 'I':
case 'C':
case 'Z':
case 'S':
case 'B':
sp += 4;
break;
default:
Debug.Assert(false);
break;
2004-08-30 19:56:23 +04:00
}
}
2005-02-18 14:50:38 +03:00
string mangledClass = JniMangle(clazz);
string mangledName = JniMangle(name);
string mangledSig = JniMangle(sig.Substring(1, sig.IndexOf(')') - 1));
string shortMethodName = String.Format("Java_{0}_{1}", mangledClass, mangledName);
string longMethodName = String.Format("Java_{0}_{1}__{2}", mangledClass, mangledName, mangledSig);
2005-02-23 15:56:15 +03:00
Tracer.Info(Tracer.Jni, "Linking native method: {0}.{1}{2}, class loader = {3}, short = {4}, long = {5}, args = {6}",
clazz, name, sig, loader, shortMethodName, longMethodName, sp + 2 * IntPtr.Size);
2004-09-09 15:17:55 +04:00
lock(JniHelper.JniLock)
{
foreach(IntPtr p in loader.GetNativeLibraries())
{
IntPtr pfunc = JniHelper.ikvm_GetProcAddress(p, shortMethodName, sp + 2 * IntPtr.Size);
if(pfunc != IntPtr.Zero)
{
2005-02-23 15:56:15 +03:00
Tracer.Info(Tracer.Jni, "Native method {0}.{1}{2} found in library 0x{3:X} (short)", clazz, name, sig, p.ToInt64());
2004-09-09 15:17:55 +04:00
return pfunc;
}
pfunc = JniHelper.ikvm_GetProcAddress(p, longMethodName, sp + 2 * IntPtr.Size);
if(pfunc != IntPtr.Zero)
{
2005-02-23 15:56:15 +03:00
Tracer.Info(Tracer.Jni, "Native method {0}.{1}{2} found in library 0x{3:X} (long)", clazz, name, sig, p.ToInt64());
2004-09-09 15:17:55 +04:00
return pfunc;
}
}
}
throw JavaException.UnsatisfiedLinkError("{0}.{1}{2}", clazz, name, sig);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
2005-02-18 14:50:38 +03:00
private static string JniMangle(string name)
{
StringBuilder sb = new StringBuilder();
foreach(char c in name)
{
if(c == '/')
{
sb.Append('_');
}
else if(c == '_')
{
sb.Append("_1");
}
else if(c == ';')
{
sb.Append("_2");
}
else if(c == '[')
{
sb.Append("_3");
}
else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
{
sb.Append(c);
}
else
{
sb.Append(String.Format("_0{0:x4}", (int)c));
}
}
return sb.ToString();
}
2004-09-09 15:17:55 +04:00
public IntPtr MakeLocalRef(object obj)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(obj == null)
{
return IntPtr.Zero;
}
int i = quickLocalIndex & JNIEnv.LOCAL_REF_MASK;
if(i < quickLocals.Length)
{
quickLocals[i] = obj;
return (IntPtr)quickLocalIndex++;
}
else if(i < JNIEnv.LOCAL_REF_BUCKET_SIZE)
{
object[] tmp = new object[quickLocals.Length * 2];
Array.Copy(quickLocals, 0, tmp, 0, quickLocals.Length);
quickLocals = tmp;
object[][] localRefs = (object[][])pJNIEnv->localRefs.Target;
localRefs[pJNIEnv->localRefSlot] = quickLocals;
quickLocals[i] = obj;
return (IntPtr)quickLocalIndex++;
}
else
{
// this can't happen, because LOCAL_REF_BUCKET_SIZE is larger than the maximum number of object
// references that can be required by a native method call (256 arguments + a class reference)
JVM.CriticalFailure("JNI.Frame.MakeLocalRef cannot spill into next slot", null);
return IntPtr.Zero;
}
}
public object UnwrapLocalRef(IntPtr p)
{
return pJNIEnv->UnwrapRef(p);
2004-08-30 19:56:23 +04:00
}
}
}
2004-09-09 15:17:55 +04:00
sealed class JniHelper
{
[DllImport("ikvm-native")]
private static extern IntPtr ikvm_LoadLibrary(string filename);
[DllImport("ikvm-native")]
private static extern void ikvm_FreeLibrary(IntPtr handle);
[DllImport("ikvm-native")]
internal static extern IntPtr ikvm_GetProcAddress(IntPtr handle, string name, int argc);
[DllImport("ikvm-native")]
private unsafe static extern int ikvm_CallOnLoad(IntPtr method, void* jvm, void* reserved);
[DllImport("ikvm-native")]
internal unsafe static extern void** ikvm_GetJNIEnvVTable();
[DllImport("ikvm-native")]
internal unsafe static extern void* ikvm_MarshalDelegate(Delegate d);
private static ArrayList nativeLibraries = new ArrayList();
internal static readonly object JniLock = new object();
2005-02-02 18:11:26 +03:00
internal unsafe static int LoadLibrary(string filename, ClassLoaderWrapper loader)
2004-08-30 19:56:23 +04:00
{
2005-02-23 15:56:15 +03:00
Tracer.Info(Tracer.Jni, "loadLibrary: {0}, class loader: {1}", filename, loader);
2004-09-09 15:17:55 +04:00
lock(JniLock)
{
IntPtr p = ikvm_LoadLibrary(filename);
if(p == IntPtr.Zero)
{
2005-02-23 15:56:15 +03:00
Tracer.Info(Tracer.Jni, "Library not found: {0}", filename);
2004-09-09 15:17:55 +04:00
return 0;
}
try
{
foreach(IntPtr tmp in loader.GetNativeLibraries())
{
if(tmp == p)
{
// the library was already loaded by the current class loader,
// no need to do anything
ikvm_FreeLibrary(p);
2005-02-23 15:56:15 +03:00
Tracer.Warning(Tracer.Jni, "Library was already loaded: {0}", filename);
2004-09-09 15:17:55 +04:00
return 1;
}
}
if(nativeLibraries.Contains(p))
{
throw JavaException.UnsatisfiedLinkError("Native library {0} already loaded in another classloader", filename);
}
2005-02-23 15:56:15 +03:00
Tracer.Info(Tracer.Jni, "Library loaded: {0}, handle = 0x{1:X}", filename, p.ToInt64());
2004-09-09 15:17:55 +04:00
IntPtr onload = ikvm_GetProcAddress(p, "JNI_OnLoad", IntPtr.Size * 2);
if(onload != IntPtr.Zero)
{
2005-02-23 15:56:15 +03:00
Tracer.Info(Tracer.Jni, "Calling JNI_OnLoad on: {0}", filename);
2004-09-09 15:17:55 +04:00
JNI.Frame f = new JNI.Frame();
2005-03-17 17:27:18 +03:00
int version;
2005-01-05 15:56:37 +03:00
ClassLoaderWrapper prevLoader = f.Enter(loader);
2005-03-17 17:27:18 +03:00
try
{
version = ikvm_CallOnLoad(onload, JavaVM.pJavaVM, null);
2006-10-19 10:12:48 +04:00
Tracer.Info(Tracer.Jni, "JNI_OnLoad returned: 0x{0:X8}", version);
2005-03-17 17:27:18 +03:00
}
finally
{
f.Leave(prevLoader);
}
2005-02-02 18:11:26 +03:00
if(!JNI.IsSupportedJniVersion(version))
2004-09-09 15:17:55 +04:00
{
throw JavaException.UnsatisfiedLinkError("Unsupported JNI version 0x{0:X} required by {1}", version, filename);
}
}
nativeLibraries.Add(p);
loader.RegisterNativeLibrary(p);
return 1;
}
catch
{
ikvm_FreeLibrary(p);
throw;
}
2004-08-30 19:56:23 +04:00
}
}
}
2004-09-09 15:17:55 +04:00
class GlobalRefs
{
internal static System.Collections.ArrayList globalRefs = new System.Collections.ArrayList();
internal static readonly object weakRefLock = new object();
internal static GCHandle[] weakRefs = new GCHandle[16];
}
unsafe class VtableBuilder
{
delegate int pf_int_IntPtr(JNIEnv* pEnv, IntPtr p);
delegate IntPtr pf_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p);
delegate void pf_void_IntPtr(JNIEnv* pEnv, IntPtr p);
delegate IntPtr pf_IntPtr(JNIEnv* pEnv);
delegate void pf_void(JNIEnv* pEnv);
delegate sbyte pf_sbyte(JNIEnv* pEnv);
delegate IntPtr pf_IntPtr_pbyte(JNIEnv* pEnv, byte* p);
delegate int pf_int(JNIEnv* pEnv);
delegate IntPtr pf_IntPtr_pbyte_IntPtr_psbyte_IntPtr(JNIEnv* pEnv, byte* p1, IntPtr p2, sbyte* p3, int p4);
delegate IntPtr pf_IntPtr_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
delegate jchar* pf_pjchar_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
2005-09-01 11:34:53 +04:00
delegate void pf_void_IntPtr_pvoid_int(JNIEnv* pEnv, IntPtr p1, void* p2, int p3);
delegate void* pf_pvoid_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
2004-09-09 15:17:55 +04:00
delegate int pf_int_IntPtr_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2);
delegate void pf_void_pbyte(JNIEnv* pEnv, byte* p1);
delegate IntPtr pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2, byte* p3);
delegate int pf_int_IntPtr_pJNINativeMethod_int(JNIEnv* pEnv, IntPtr p1, JNIEnv.JNINativeMethod* p2, int p3);
delegate int pf_int_ppJavaVM(JNIEnv* pEnv, JavaVM** ppJavaVM);
delegate sbyte pf_sbyte_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
delegate short pf_short_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
delegate ushort pf_ushort_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
delegate int pf_int_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
delegate long pf_long_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
delegate float pf_float_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
delegate double pf_double_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
delegate void pf_void_IntPtr_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3);
delegate void pf_void_IntPtr_IntPtr_sbyte(JNIEnv* pEnv, IntPtr p1, IntPtr p2, sbyte p3);
delegate void pf_void_IntPtr_IntPtr_short(JNIEnv* pEnv, IntPtr p1, IntPtr p2, short p3);
delegate void pf_void_IntPtr_IntPtr_ushort(JNIEnv* pEnv, IntPtr p1, IntPtr p2, ushort p3);
delegate void pf_void_IntPtr_IntPtr_int(JNIEnv* pEnv, IntPtr p1, IntPtr p2, int p3);
delegate void pf_void_IntPtr_IntPtr_long(JNIEnv* pEnv, IntPtr p1, IntPtr p2, long p3);
delegate void pf_void_IntPtr_IntPtr_float(JNIEnv* pEnv, IntPtr p1, IntPtr p2, float p3);
delegate void pf_void_IntPtr_IntPtr_double(JNIEnv* pEnv, IntPtr p1, IntPtr p2, double p3);
delegate IntPtr pf_IntPtr_pjchar_int(JNIEnv* pEnv, jchar* p1, int p2);
delegate void pf_void_IntPtr_IntPtr(JNIEnv* pEnv, IntPtr p1, IntPtr p2);
delegate void pf_void_IntPtr_pjchar(JNIEnv* pEnv, IntPtr p1, jchar* p2);
delegate IntPtr pf_IntPtr_int_IntPtr_IntPtr(JNIEnv* pEnv, int p1, IntPtr p2, IntPtr p3);
delegate IntPtr pf_IntPtr_IntPtr_int(JNIEnv* pEnv, IntPtr p1, int p2);
delegate void pf_void_IntPtr_int_IntPtr(JNIEnv* pEnv, IntPtr p1, int p2, IntPtr p3);
delegate IntPtr pf_IntPtr_int(JNIEnv* pEnv, int p1);
delegate void pf_void_IntPtr_int_int_IntPtr(JNIEnv* pEnv, IntPtr p1, int p2, int p3, IntPtr p4);
delegate IntPtr pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
delegate sbyte pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
delegate short pf_short_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
delegate ushort pf_ushort_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
delegate int pf_int_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
delegate long pf_long_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
delegate float pf_float_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
delegate double pf_double_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
delegate void pf_void_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, JNIEnv.jvalue* p3);
delegate IntPtr pf_IntPtr_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
delegate sbyte pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
delegate ushort pf_ushort_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
delegate short pf_short_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
delegate int pf_int_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
delegate long pf_long_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
delegate float pf_float_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
delegate double pf_double_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
delegate void pf_void_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv* pEnv, IntPtr p1, IntPtr p2, IntPtr p3, JNIEnv.jvalue* p4);
delegate byte* pf_pbyte_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
delegate void pf_void_IntPtr_pbyte(JNIEnv* pEnv, IntPtr p1, byte* p2);
delegate jboolean* pf_pjboolean_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
delegate jbyte* pf_pjbyte_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
delegate jshort* pf_pjshort_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
delegate jint* pf_pjint_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
delegate jlong* pf_pjlong_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
delegate jfloat* pf_pjfloat_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
delegate jdouble* pf_pjdouble_IntPtr_pjboolean(JNIEnv* pEnv, IntPtr p1, jboolean* p2);
delegate void pf_void_IntPtr_pjboolean_int(JNIEnv* pEnv, IntPtr p1, jboolean* p2, int p3);
delegate void pf_void_IntPtr_pjbyte_int(JNIEnv* pEnv, IntPtr p1, jbyte* p2, int p3);
delegate void pf_void_IntPtr_pjchar_int(JNIEnv* pEnv, IntPtr p1, jchar* p2, int p3);
delegate void pf_void_IntPtr_pjshort_int(JNIEnv* pEnv, IntPtr p1, jshort* p2, int p3);
delegate void pf_void_IntPtr_pjint_int(JNIEnv* pEnv, IntPtr p1, jint* p2, int p3);
delegate void pf_void_IntPtr_pjlong_int(JNIEnv* pEnv, IntPtr p1, jlong* p2, int p3);
delegate void pf_void_IntPtr_pjfloat_int(JNIEnv* pEnv, IntPtr p1, jfloat* p2, int p3);
delegate void pf_void_IntPtr_pjdouble_int(JNIEnv* pEnv, IntPtr p1, jdouble* p2, int p3);
delegate int pf_int_int(JNIEnv* pEnv, int p1);
2004-11-23 20:46:39 +03:00
delegate IntPtr pf_IntPtr_IntPtr_long(JNIEnv* pEnv, IntPtr p1, long p2);
delegate long pf_long_IntPtr(JNIEnv* pEnv, IntPtr p1);
2005-05-17 17:18:16 +04:00
delegate IntPtr pf_IntPtr_IntPtr_IntPtr_sbyte(JNIEnv* pEnv, IntPtr p1, IntPtr p2, sbyte p3);
2004-09-09 15:17:55 +04:00
internal static void* vtable;
static VtableBuilder()
{
2005-02-23 15:56:15 +03:00
JNI.jvmCreated = true;
2004-09-09 15:17:55 +04:00
// JNIEnv
void** pmcpp = JniHelper.ikvm_GetJNIEnvVTable();
void** p = (void**)JniMem.Alloc(IntPtr.Size * vtableDelegates.Length);
for(int i = 0; i < vtableDelegates.Length; i++)
{
if(vtableDelegates[i] != null)
{
p[i] = JniHelper.ikvm_MarshalDelegate(vtableDelegates[i]);
}
else
{
p[i] = pmcpp[i];
}
}
vtable = p;
}
static Delegate[] vtableDelegates =
2004-08-30 19:56:23 +04:00
{
new pf_int_IntPtr_pbyte(JNIEnv.GetMethodArgs), //virtual void JNICALL reserved0();
null, //virtual void JNICALL reserved1();
null, //virtual void JNICALL reserved2();
null, //virtual void JNICALL reserved3();
new pf_int(JNIEnv.GetVersion), //virtual jint JNICALL GetVersion();
2004-09-05 13:37:58 +04:00
new pf_IntPtr_pbyte_IntPtr_psbyte_IntPtr(JNIEnv.DefineClass), //virtual jclass JNICALL DefineClass(const char *name, jobject loader, const jbyte *buf, jsize len);
2004-08-30 19:56:23 +04:00
new pf_IntPtr_pbyte(JNIEnv.FindClass), //virtual jclass JNICALL FindClass(const char *name);
new pf_IntPtr_IntPtr(JNIEnv.FromReflectedMethod), //virtual jmethodID JNICALL FromReflectedMethod(jobject method);
new pf_IntPtr_IntPtr(JNIEnv.FromReflectedField), //virtual jfieldID JNICALL FromReflectedField(jobject field);
2005-05-17 17:18:16 +04:00
new pf_IntPtr_IntPtr_IntPtr_sbyte(JNIEnv.ToReflectedMethod), //virtual jobject JNICALL ToReflectedMethod(jclass clazz, jmethodID methodID, jboolean isStatic);
2004-08-30 19:56:23 +04:00
new pf_IntPtr_IntPtr(JNIEnv.GetSuperclass), //virtual jclass JNICALL GetSuperclass(jclass sub);
new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsAssignableFrom), //virtual jboolean JNICALL IsAssignableFrom(jclass sub, jclass sup);
2005-05-17 17:18:16 +04:00
new pf_IntPtr_IntPtr_IntPtr_sbyte(JNIEnv.ToReflectedField), //virtual jobject JNICALL ToReflectedField(jclass clazz, jfieldID fieldID, jboolean isStatic);
2004-08-30 19:56:23 +04:00
new pf_int_IntPtr(JNIEnv.Throw), //virtual jint JNICALL Throw(jthrowable obj);
new pf_int_IntPtr_pbyte(JNIEnv.ThrowNew), //virtual jint JNICALL ThrowNew(jclass clazz, const char *msg);
new pf_IntPtr(JNIEnv.ExceptionOccurred), //virtual jthrowable JNICALL ExceptionOccurred();
new pf_void(JNIEnv.ExceptionDescribe), //virtual void JNICALL ExceptionDescribe();
new pf_void(JNIEnv.ExceptionClear), //virtual void JNICALL ExceptionClear();
new pf_void_pbyte(JNIEnv.FatalError), //virtual void JNICALL FatalError(const char *msg);
2004-09-05 13:37:58 +04:00
new pf_int_int(JNIEnv.PushLocalFrame), //virtual jint JNICALL PushLocalFrame(jint capacity);
new pf_IntPtr_IntPtr(JNIEnv.PopLocalFrame), //virtual jobject JNICALL PopLocalFrame(jobject result);
2004-08-30 19:56:23 +04:00
new pf_IntPtr_IntPtr(JNIEnv.NewGlobalRef), //virtual jobject JNICALL NewGlobalRef(jobject lobj);
new pf_void_IntPtr(JNIEnv.DeleteGlobalRef), //virtual void JNICALL DeleteGlobalRef(jobject gref);
new pf_void_IntPtr(JNIEnv.DeleteLocalRef), //virtual void JNICALL DeleteLocalRef(jobject obj);
new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsSameObject), //virtual jboolean JNICALL IsSameObject(jobject obj1, jobject obj2);
new pf_IntPtr_IntPtr(JNIEnv.NewLocalRef), //virtual jobject JNICALL NewLocalRef(jobject ref);
2004-09-05 13:37:58 +04:00
new pf_int_int(JNIEnv.EnsureLocalCapacity), //virtual jint JNICALL EnsureLocalCapacity(jint capacity);
2004-08-30 19:56:23 +04:00
new pf_IntPtr_IntPtr(JNIEnv.AllocObject), //virtual jobject JNICALL AllocObject(jclass clazz);
null, //virtual jobject JNICALL NewObject(jclass clazz, jmethodID methodID, ...);
null, //virtual jobject JNICALL NewObjectV(jclass clazz, jmethodID methodID, va_list args);
new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.NewObjectA), //virtual jobject JNICALL NewObjectA(jclass clazz, jmethodID methodID, jvalue *args);
new pf_IntPtr_IntPtr(JNIEnv.GetObjectClass), //virtual jclass JNICALL GetObjectClass(jobject obj);
new pf_sbyte_IntPtr_IntPtr(JNIEnv.IsInstanceOf), //virtual jboolean JNICALL IsInstanceOf(jobject obj, jclass clazz);
new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetMethodID), //virtual jmethodID JNICALL GetMethodID(jclass clazz, const char *name, const char *sig);
null, //virtual jobject JNICALL CallObjectMethod(jobject obj, jmethodID methodID, ...);
null, //virtual jobject JNICALL CallObjectMethodV(jobject obj, jmethodID methodID, va_list args);
new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallObjectMethodA), //virtual jobject JNICALL CallObjectMethodA(jobject obj, jmethodID methodID, jvalue * args);
null, //virtual jboolean JNICALL CallBooleanMethod(jobject obj, jmethodID methodID, ...);
null, //virtual jboolean JNICALL CallBooleanMethodV(jobject obj, jmethodID methodID, va_list args);
new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallBooleanMethodA), //virtual jboolean JNICALL CallBooleanMethodA(jobject obj, jmethodID methodID, jvalue * args);
null, //virtual jbyte JNICALL CallByteMethod(jobject obj, jmethodID methodID, ...);
null, //virtual jbyte JNICALL CallByteMethodV(jobject obj, jmethodID methodID, va_list args);
new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallByteMethodA), //virtual jbyte JNICALL CallByteMethodA(jobject obj, jmethodID methodID, jvalue *args);
null, //virtual jchar JNICALL CallCharMethod(jobject obj, jmethodID methodID, ...);
null, //virtual jchar JNICALL CallCharMethodV(jobject obj, jmethodID methodID, va_list args);
2004-09-05 13:37:58 +04:00
new pf_ushort_IntPtr_IntPtr_pjvalue(JNIEnv.CallCharMethodA), //virtual jchar JNICALL CallCharMethodA(jobject obj, jmethodID methodID, jvalue *args);
2004-08-30 19:56:23 +04:00
null, //virtual jshort JNICALL CallShortMethod(jobject obj, jmethodID methodID, ...);
null, //virtual jshort JNICALL CallShortMethodV(jobject obj, jmethodID methodID, va_list args);
new pf_short_IntPtr_IntPtr_pjvalue(JNIEnv.CallShortMethodA), //virtual jshort JNICALL CallShortMethodA(jobject obj, jmethodID methodID, jvalue *args);
null, //virtual jint JNICALL CallIntMethod(jobject obj, jmethodID methodID, ...);
null, //virtual jint JNICALL CallIntMethodV(jobject obj, jmethodID methodID, va_list args);
new pf_int_IntPtr_IntPtr_pjvalue(JNIEnv.CallIntMethodA), //virtual jint JNICALL CallIntMethodA(jobject obj, jmethodID methodID, jvalue *args);
null, //virtual jlong JNICALL CallLongMethod(jobject obj, jmethodID methodID, ...);
null, //virtual jlong JNICALL CallLongMethodV(jobject obj, jmethodID methodID, va_list args);
new pf_long_IntPtr_IntPtr_pjvalue(JNIEnv.CallLongMethodA), //virtual jlong JNICALL CallLongMethodA(jobject obj, jmethodID methodID, jvalue *args);
null, //virtual jfloat JNICALL CallFloatMethod(jobject obj, jmethodID methodID, ...);
null, //virtual jfloat JNICALL CallFloatMethodV(jobject obj, jmethodID methodID, va_list args);
new pf_float_IntPtr_IntPtr_pjvalue(JNIEnv.CallFloatMethodA), //virtual jfloat JNICALL CallFloatMethodA(jobject obj, jmethodID methodID, jvalue *args);
null, //virtual jdouble JNICALL CallDoubleMethod(jobject obj, jmethodID methodID, ...);
null, //virtual jdouble JNICALL CallDoubleMethodV(jobject obj, jmethodID methodID, va_list args);
new pf_double_IntPtr_IntPtr_pjvalue(JNIEnv.CallDoubleMethodA), //virtual jdouble JNICALL CallDoubleMethodA(jobject obj, jmethodID methodID, jvalue *args);
null, //virtual void JNICALL CallVoidMethod(jobject obj, jmethodID methodID, ...);
null, //virtual void JNICALL CallVoidMethodV(jobject obj, jmethodID methodID, va_list args);
new pf_void_IntPtr_IntPtr_pjvalue(JNIEnv.CallVoidMethodA), //virtual void JNICALL CallVoidMethodA(jobject obj, jmethodID methodID, jvalue * args);
null, //virtual jobject JNICALL CallNonvirtualObjectMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
null, //virtual jobject JNICALL CallNonvirtualObjectMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
new pf_IntPtr_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualObjectMethodA), //virtual jobject JNICALL CallNonvirtualObjectMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args);
null, //virtual jboolean JNICALL CallNonvirtualBooleanMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
null, //virtual jboolean JNICALL CallNonvirtualBooleanMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
new pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualBooleanMethodA), //virtual jboolean JNICALL CallNonvirtualBooleanMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args);
null, //virtual jbyte JNICALL CallNonvirtualByteMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
null, //virtual jbyte JNICALL CallNonvirtualByteMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
new pf_sbyte_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualByteMethodA), //virtual jbyte JNICALL CallNonvirtualByteMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jchar JNICALL CallNonvirtualCharMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
null, //virtual jchar JNICALL CallNonvirtualCharMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
2004-09-05 13:37:58 +04:00
new pf_ushort_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualCharMethodA), //virtual jchar JNICALL CallNonvirtualCharMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
2004-08-30 19:56:23 +04:00
null, //virtual jshort JNICALL CallNonvirtualShortMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
null, //virtual jshort JNICALL CallNonvirtualShortMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
new pf_short_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualShortMethodA), //virtual jshort JNICALL CallNonvirtualShortMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jint JNICALL CallNonvirtualIntMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
null, //virtual jint JNICALL CallNonvirtualIntMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
new pf_int_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualIntMethodA), //virtual jint JNICALL CallNonvirtualIntMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jlong JNICALL CallNonvirtualLongMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
null, //virtual jlong JNICALL CallNonvirtualLongMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
new pf_long_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualLongMethodA), //virtual jlong JNICALL CallNonvirtualLongMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jfloat JNICALL CallNonvirtualFloatMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
null, //virtual jfloat JNICALL CallNonvirtualFloatMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
new pf_float_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualFloatMethodA), //virtual jfloat JNICALL CallNonvirtualFloatMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jdouble JNICALL CallNonvirtualDoubleMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
null, //virtual jdouble JNICALL CallNonvirtualDoubleMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
new pf_double_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualDoubleMethodA), //virtual jdouble JNICALL CallNonvirtualDoubleMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual void JNICALL CallNonvirtualVoidMethod(jobject obj, jclass clazz, jmethodID methodID, ...);
null, //virtual void JNICALL CallNonvirtualVoidMethodV(jobject obj, jclass clazz, jmethodID methodID, va_list args);
new pf_void_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallNonvirtualVoidMethodA), //virtual void JNICALL CallNonvirtualVoidMethodA(jobject obj, jclass clazz, jmethodID methodID, jvalue * args);
new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetFieldID), //virtual jfieldID JNICALL GetFieldID(jclass clazz, const char *name, const char *sig);
new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetObjectField), //virtual jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID);
new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetBooleanField), //virtual jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID);
new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetByteField), //virtual jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID);
2004-09-05 13:37:58 +04:00
new pf_ushort_IntPtr_IntPtr(JNIEnv.GetCharField), //virtual jchar JNICALL GetCharField(jobject obj, jfieldID fieldID);
2004-08-30 19:56:23 +04:00
new pf_short_IntPtr_IntPtr(JNIEnv.GetShortField), //virtual jshort JNICALL GetShortField(jobject obj, jfieldID fieldID);
new pf_int_IntPtr_IntPtr(JNIEnv.GetIntField), //virtual jint JNICALL GetIntField(jobject obj, jfieldID fieldID);
new pf_long_IntPtr_IntPtr(JNIEnv.GetLongField), //virtual jlong JNICALL GetLongField(jobject obj, jfieldID fieldID);
new pf_float_IntPtr_IntPtr(JNIEnv.GetFloatField), //virtual jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID);
new pf_double_IntPtr_IntPtr(JNIEnv.GetDoubleField), //virtual jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID);
new pf_void_IntPtr_IntPtr_IntPtr(JNIEnv.SetObjectField), //virtual void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val);
new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetBooleanField), //virtual void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val);
new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetByteField), //virtual void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val);
2004-09-05 13:37:58 +04:00
new pf_void_IntPtr_IntPtr_ushort(JNIEnv.SetCharField), //virtual void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val);
2004-08-30 19:56:23 +04:00
new pf_void_IntPtr_IntPtr_short(JNIEnv.SetShortField), //virtual void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val);
new pf_void_IntPtr_IntPtr_int(JNIEnv.SetIntField), //virtual void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val);
new pf_void_IntPtr_IntPtr_long(JNIEnv.SetLongField), //virtual void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val);
new pf_void_IntPtr_IntPtr_float(JNIEnv.SetFloatField), //virtual void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val);
new pf_void_IntPtr_IntPtr_double(JNIEnv.SetDoubleField), //virtual void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val);
new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetStaticMethodID), //virtual jmethodID JNICALL GetStaticMethodID(jclass clazz, const char *name, const char *sig);
null, //virtual jobject JNICALL CallStaticObjectMethod(jclass clazz, jmethodID methodID, ...);
null, //virtual jobject JNICALL CallStaticObjectMethodV(jclass clazz, jmethodID methodID, va_list args);
new pf_IntPtr_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticObjectMethodA), //virtual jobject JNICALL CallStaticObjectMethodA(jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jboolean JNICALL CallStaticBooleanMethod(jclass clazz, jmethodID methodID, ...);
null, //virtual jboolean JNICALL CallStaticBooleanMethodV(jclass clazz, jmethodID methodID, va_list args);
new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticBooleanMethodA), //virtual jboolean JNICALL CallStaticBooleanMethodA(jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jbyte JNICALL CallStaticByteMethod(jclass clazz, jmethodID methodID, ...);
null, //virtual jbyte JNICALL CallStaticByteMethodV(jclass clazz, jmethodID methodID, va_list args);
new pf_sbyte_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticByteMethodA), //virtual jbyte JNICALL CallStaticByteMethodA(jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jchar JNICALL CallStaticCharMethod(jclass clazz, jmethodID methodID, ...);
null, //virtual jchar JNICALL CallStaticCharMethodV(jclass clazz, jmethodID methodID, va_list args);
2004-09-05 13:37:58 +04:00
new pf_ushort_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticCharMethodA), //virtual jchar JNICALL CallStaticCharMethodA(jclass clazz, jmethodID methodID, jvalue *args);
2004-08-30 19:56:23 +04:00
null, //virtual jshort JNICALL CallStaticShortMethod(jclass clazz, jmethodID methodID, ...);
null, //virtual jshort JNICALL CallStaticShortMethodV(jclass clazz, jmethodID methodID, va_list args);
new pf_short_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticShortMethodA), //virtual jshort JNICALL CallStaticShortMethodA(jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jint JNICALL CallStaticIntMethod(jclass clazz, jmethodID methodID, ...);
null, //virtual jint JNICALL CallStaticIntMethodV(jclass clazz, jmethodID methodID, va_list args);
new pf_int_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticIntMethodA), //virtual jint JNICALL CallStaticIntMethodA(jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jlong JNICALL CallStaticLongMethod(jclass clazz, jmethodID methodID, ...);
null, //virtual jlong JNICALL CallStaticLongMethodV(jclass clazz, jmethodID methodID, va_list args);
new pf_long_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticLongMethodA), //virtual jlong JNICALL CallStaticLongMethodA(jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jfloat JNICALL CallStaticFloatMethod(jclass clazz, jmethodID methodID, ...);
null, //virtual jfloat JNICALL CallStaticFloatMethodV(jclass clazz, jmethodID methodID, va_list args);
new pf_float_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticFloatMethodA), //virtual jfloat JNICALL CallStaticFloatMethodA(jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual jdouble JNICALL CallStaticDoubleMethod(jclass clazz, jmethodID methodID, ...);
null, //virtual jdouble JNICALL CallStaticDoubleMethodV(jclass clazz, jmethodID methodID, va_list args);
new pf_double_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticDoubleMethodA), //virtual jdouble JNICALL CallStaticDoubleMethodA(jclass clazz, jmethodID methodID, jvalue *args);
null, //virtual void JNICALL CallStaticVoidMethod(jclass cls, jmethodID methodID, ...);
null, //virtual void JNICALL CallStaticVoidMethodV(jclass cls, jmethodID methodID, va_list args);
new pf_void_IntPtr_IntPtr_pjvalue(JNIEnv.CallStaticVoidMethodA), //virtual void JNICALL CallStaticVoidMethodA(jclass cls, jmethodID methodID, jvalue * args);
new pf_IntPtr_IntPtr_pbyte_pbyte(JNIEnv.GetStaticFieldID), //virtual jfieldID JNICALL GetStaticFieldID(jclass clazz, const char *name, const char *sig);
new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetStaticObjectField), //virtual jobject JNICALL GetObjectField(jobject obj, jfieldID fieldID);
new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetStaticBooleanField), //virtual jboolean JNICALL GetBooleanField(jobject obj, jfieldID fieldID);
new pf_sbyte_IntPtr_IntPtr(JNIEnv.GetStaticByteField), //virtual jbyte JNICALL GetByteField(jobject obj, jfieldID fieldID);
2004-09-05 13:37:58 +04:00
new pf_ushort_IntPtr_IntPtr(JNIEnv.GetStaticCharField), //virtual jchar JNICALL GetCharField(jobject obj, jfieldID fieldID);
2004-08-30 19:56:23 +04:00
new pf_short_IntPtr_IntPtr(JNIEnv.GetStaticShortField), //virtual jshort JNICALL GetShortField(jobject obj, jfieldID fieldID);
new pf_int_IntPtr_IntPtr(JNIEnv.GetStaticIntField), //virtual jint JNICALL GetIntField(jobject obj, jfieldID fieldID);
new pf_long_IntPtr_IntPtr(JNIEnv.GetStaticLongField), //virtual jlong JNICALL GetLongField(jobject obj, jfieldID fieldID);
new pf_float_IntPtr_IntPtr(JNIEnv.GetStaticFloatField), //virtual jfloat JNICALL GetFloatField(jobject obj, jfieldID fieldID);
new pf_double_IntPtr_IntPtr(JNIEnv.GetStaticDoubleField), //virtual jdouble JNICALL GetDoubleField(jobject obj, jfieldID fieldID);
new pf_void_IntPtr_IntPtr_IntPtr(JNIEnv.SetStaticObjectField), //virtual void JNICALL SetObjectField(jobject obj, jfieldID fieldID, jobject val);
new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetStaticBooleanField), //virtual void JNICALL SetBooleanField(jobject obj, jfieldID fieldID, jboolean val);
new pf_void_IntPtr_IntPtr_sbyte(JNIEnv.SetStaticByteField), //virtual void JNICALL SetByteField(jobject obj, jfieldID fieldID, jbyte val);
2004-09-05 13:37:58 +04:00
new pf_void_IntPtr_IntPtr_ushort(JNIEnv.SetStaticCharField), //virtual void JNICALL SetCharField(jobject obj, jfieldID fieldID, jchar val);
2004-08-30 19:56:23 +04:00
new pf_void_IntPtr_IntPtr_short(JNIEnv.SetStaticShortField), //virtual void JNICALL SetShortField(jobject obj, jfieldID fieldID, jshort val);
new pf_void_IntPtr_IntPtr_int(JNIEnv.SetStaticIntField), //virtual void JNICALL SetIntField(jobject obj, jfieldID fieldID, jint val);
new pf_void_IntPtr_IntPtr_long(JNIEnv.SetStaticLongField), //virtual void JNICALL SetLongField(jobject obj, jfieldID fieldID, jlong val);
new pf_void_IntPtr_IntPtr_float(JNIEnv.SetStaticFloatField), //virtual void JNICALL SetFloatField(jobject obj, jfieldID fieldID, jfloat val);
new pf_void_IntPtr_IntPtr_double(JNIEnv.SetStaticDoubleField), //virtual void JNICALL SetDoubleField(jobject obj, jfieldID fieldID, jdouble val);
2004-09-05 13:37:58 +04:00
new pf_IntPtr_pjchar_int(JNIEnv.NewString), //virtual jstring JNICALL NewString(const jchar *unicode, jsize len);
2004-08-30 19:56:23 +04:00
new pf_int_IntPtr(JNIEnv.GetStringLength), //virtual jsize JNICALL GetStringLength(jstring str);
2004-09-05 13:37:58 +04:00
new pf_pjchar_IntPtr_pjboolean(JNIEnv.GetStringChars), //virtual const jchar *JNICALL GetStringChars(jstring str, jboolean *isCopy);
new pf_void_IntPtr_pjchar(JNIEnv.ReleaseStringChars), //virtual void JNICALL ReleaseStringChars(jstring str, const jchar *chars);
2004-08-30 19:56:23 +04:00
2004-09-05 13:37:58 +04:00
new pf_IntPtr_pbyte(JNIEnv.NewStringUTF), //virtual jstring JNICALL NewStringUTF(const char *utf);
2004-08-30 19:56:23 +04:00
new pf_int_IntPtr(JNIEnv.GetStringUTFLength), //virtual jsize JNICALL GetStringUTFLength(jstring str);
2004-09-05 13:37:58 +04:00
new pf_pbyte_IntPtr_pjboolean(JNIEnv.GetStringUTFChars), //virtual const char* JNICALL GetStringUTFChars(jstring str, jboolean *isCopy);
new pf_void_IntPtr_pbyte(JNIEnv.ReleaseStringUTFChars), //virtual void JNICALL ReleaseStringUTFChars(jstring str, const char* chars);
2004-08-30 19:56:23 +04:00
new pf_int_IntPtr(JNIEnv.GetArrayLength), //virtual jsize JNICALL GetArrayLength(jarray array);
new pf_IntPtr_int_IntPtr_IntPtr(JNIEnv.NewObjectArray), //virtual jobjectArray JNICALL NewObjectArray(jsize len, jclass clazz, jobject init);
new pf_IntPtr_IntPtr_int(JNIEnv.GetObjectArrayElement), //virtual jobject JNICALL GetObjectArrayElement(jobjectArray array, jsize index);
new pf_void_IntPtr_int_IntPtr(JNIEnv.SetObjectArrayElement), //virtual void JNICALL SetObjectArrayElement(jobjectArray array, jsize index, jobject val);
new pf_IntPtr_int(JNIEnv.NewBooleanArray), //virtual jbooleanArray JNICALL NewBooleanArray(jsize len);
new pf_IntPtr_int(JNIEnv.NewByteArray), //virtual jbyteArray JNICALL NewByteArray(jsize len);
new pf_IntPtr_int(JNIEnv.NewCharArray), //virtual jcharArray JNICALL NewCharArray(jsize len);
new pf_IntPtr_int(JNIEnv.NewShortArray), //virtual jshortArray JNICALL NewShortArray(jsize len);
new pf_IntPtr_int(JNIEnv.NewIntArray), //virtual jintArray JNICALL NewIntArray(jsize len);
new pf_IntPtr_int(JNIEnv.NewLongArray), //virtual jlongArray JNICALL NewLongArray(jsize len);
new pf_IntPtr_int(JNIEnv.NewFloatArray), //virtual jfloatArray JNICALL NewFloatArray(jsize len);
new pf_IntPtr_int(JNIEnv.NewDoubleArray), //virtual jdoubleArray JNICALL NewDoubleArray(jsize len);
2004-09-05 13:37:58 +04:00
new pf_pjboolean_IntPtr_pjboolean(JNIEnv.GetBooleanArrayElements), //virtual jboolean * JNICALL GetBooleanArrayElements(jbooleanArray array, jboolean *isCopy);
new pf_pjbyte_IntPtr_pjboolean(JNIEnv.GetByteArrayElements), //virtual jbyte * JNICALL GetByteArrayElements(jbyteArray array, jboolean *isCopy);
new pf_pjchar_IntPtr_pjboolean(JNIEnv.GetCharArrayElements), //virtual jchar * JNICALL GetCharArrayElements(jcharArray array, jboolean *isCopy);
new pf_pjshort_IntPtr_pjboolean(JNIEnv.GetShortArrayElements), //virtual jshort * JNICALL GetShortArrayElements(jshortArray array, jboolean *isCopy);
new pf_pjint_IntPtr_pjboolean(JNIEnv.GetIntArrayElements), //virtual jint * JNICALL GetIntArrayElements(jintArray array, jboolean *isCopy);
new pf_pjlong_IntPtr_pjboolean(JNIEnv.GetLongArrayElements), //virtual jlong * JNICALL GetLongArrayElements(jlongArray array, jboolean *isCopy);
new pf_pjfloat_IntPtr_pjboolean(JNIEnv.GetFloatArrayElements), //virtual jfloat * JNICALL GetFloatArrayElements(jfloatArray array, jboolean *isCopy);
new pf_pjdouble_IntPtr_pjboolean(JNIEnv.GetDoubleArrayElements), //virtual jdouble * JNICALL GetDoubleArrayElements(jdoubleArray array, jboolean *isCopy);
new pf_void_IntPtr_pjboolean_int(JNIEnv.ReleaseBooleanArrayElements), //virtual void JNICALL ReleaseBooleanArrayElements(jbooleanArray array, jboolean *elems, jint mode);
new pf_void_IntPtr_pjbyte_int(JNIEnv.ReleaseByteArrayElements), //virtual void JNICALL ReleaseByteArrayElements(jbyteArray array, jbyte *elems, jint mode);
new pf_void_IntPtr_pjchar_int(JNIEnv.ReleaseCharArrayElements), //virtual void JNICALL ReleaseCharArrayElements(jcharArray array, jchar *elems, jint mode);
new pf_void_IntPtr_pjshort_int(JNIEnv.ReleaseShortArrayElements), //virtual void JNICALL ReleaseShortArrayElements(jshortArray array, jshort *elems, jint mode);
new pf_void_IntPtr_pjint_int(JNIEnv.ReleaseIntArrayElements), //virtual void JNICALL ReleaseIntArrayElements(jintArray array, jint *elems, jint mode);
new pf_void_IntPtr_pjlong_int(JNIEnv.ReleaseLongArrayElements), //virtual void JNICALL ReleaseLongArrayElements(jlongArray array, jlong *elems, jint mode);
new pf_void_IntPtr_pjfloat_int(JNIEnv.ReleaseFloatArrayElements), //virtual void JNICALL ReleaseFloatArrayElements(jfloatArray array, jfloat *elems, jint mode);
new pf_void_IntPtr_pjdouble_int(JNIEnv.ReleaseDoubleArrayElements), //virtual void JNICALL ReleaseDoubleArrayElements(jdoubleArray array, jdouble *elems, jint mode);
2004-08-30 19:56:23 +04:00
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetBooleanArrayRegion), //virtual void JNICALL GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetByteArrayRegion), //virtual void JNICALL GetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetCharArrayRegion), //virtual void JNICALL GetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetShortArrayRegion), //virtual void JNICALL GetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetIntArrayRegion), //virtual void JNICALL GetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetLongArrayRegion), //virtual void JNICALL GetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetFloatArrayRegion), //virtual void JNICALL GetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetDoubleArrayRegion), //virtual void JNICALL GetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetBooleanArrayRegion), //virtual void JNICALL SetBooleanArrayRegion(jbooleanArray array, jsize start, jsize l, jboolean *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetByteArrayRegion), //virtual void JNICALL SetByteArrayRegion(jbyteArray array, jsize start, jsize len, jbyte *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetCharArrayRegion), //virtual void JNICALL SetCharArrayRegion(jcharArray array, jsize start, jsize len, jchar *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetShortArrayRegion), //virtual void JNICALL SetShortArrayRegion(jshortArray array, jsize start, jsize len, jshort *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetIntArrayRegion), //virtual void JNICALL SetIntArrayRegion(jintArray array, jsize start, jsize len, jint *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetLongArrayRegion), //virtual void JNICALL SetLongArrayRegion(jlongArray array, jsize start, jsize len, jlong *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetFloatArrayRegion), //virtual void JNICALL SetFloatArrayRegion(jfloatArray array, jsize start, jsize len, jfloat *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.SetDoubleArrayRegion), //virtual void JNICALL SetDoubleArrayRegion(jdoubleArray array, jsize start, jsize len, jdouble *buf);
new pf_int_IntPtr_pJNINativeMethod_int(JNIEnv.RegisterNatives), //virtual jint JNICALL RegisterNatives(jclass clazz, const JNINativeMethod *methods, jint nMethods);
new pf_int_IntPtr(JNIEnv.UnregisterNatives), //virtual jint JNICALL UnregisterNatives(jclass clazz);
new pf_int_IntPtr(JNIEnv.MonitorEnter), //virtual jint JNICALL MonitorEnter(jobject obj);
new pf_int_IntPtr(JNIEnv.MonitorExit), //virtual jint JNICALL MonitorExit(jobject obj);
new pf_int_ppJavaVM(JNIEnv.GetJavaVM), //virtual jint JNICALL GetJavaVM(JavaVM **vm);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetStringRegion), //virtual void JNICALL GetStringRegion(jstring str, jsize start, jsize len, jchar *buf);
new pf_void_IntPtr_int_int_IntPtr(JNIEnv.GetStringUTFRegion), //virtual void JNICALL GetStringUTFRegion(jstring str, jsize start, jsize len, char *buf);
2005-09-01 11:34:53 +04:00
new pf_pvoid_IntPtr_pjboolean(JNIEnv.GetPrimitiveArrayCritical), //virtual void* JNICALL GetPrimitiveArrayCritical(jarray array, jboolean *isCopy);
new pf_void_IntPtr_pvoid_int(JNIEnv.ReleasePrimitiveArrayCritical), //virtual void JNICALL ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode);
2004-08-30 19:56:23 +04:00
2005-09-01 11:34:53 +04:00
new pf_pjchar_IntPtr_pjboolean(JNIEnv.GetStringCritical), //virtual const jchar* JNICALL GetStringCritical(jstring string, jboolean *isCopy);
new pf_void_IntPtr_pjchar(JNIEnv.ReleaseStringCritical), //virtual void JNICALL ReleaseStringCritical(jstring string, const jchar *cstring);
2004-08-30 19:56:23 +04:00
2004-09-05 13:37:58 +04:00
new pf_IntPtr_IntPtr(JNIEnv.NewWeakGlobalRef), //virtual jweak JNICALL NewWeakGlobalRef(jobject obj);
new pf_void_IntPtr(JNIEnv.DeleteWeakGlobalRef), //virtual void JNICALL DeleteWeakGlobalRef(jweak ref);
2004-08-30 19:56:23 +04:00
new pf_sbyte(JNIEnv.ExceptionCheck), //virtual jboolean JNICALL ExceptionCheck();
2004-11-23 20:46:39 +03:00
new pf_IntPtr_IntPtr_long(JNIEnv.NewDirectByteBuffer), //virtual jobject JNICALL NewDirectByteBuffer(void* address, jlong capacity);
new pf_IntPtr_IntPtr(JNIEnv.GetDirectBufferAddress), //virtual void* JNICALL GetDirectBufferAddress(jobject buf);
new pf_long_IntPtr(JNIEnv.GetDirectBufferCapacity) //virtual jlong JNICALL GetDirectBufferCapacity(jobject buf);
2004-08-30 19:56:23 +04:00
};
2004-09-09 15:17:55 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
[StructLayout(LayoutKind.Sequential)]
unsafe struct JavaVMAttachArgs
{
internal jint version;
internal byte* name;
2004-09-09 15:17:55 +04:00
internal jobject group;
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct JavaVM
{
internal static JavaVM* pJavaVM;
void** vtable;
void* firstVtableEntry;
delegate int pf_int(JavaVM* pJVM);
delegate int pf_int_ppvoid_pvoid(JavaVM* pJVM, void** p1, void* p2);
delegate int pf_int_ppvoid_int(JavaVM* pJVM, void** p1, int p2);
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
static Delegate[] vtableDelegates =
2004-08-30 19:56:23 +04:00
{
null,
null,
null,
new pf_int(DestroyJavaVM),
new pf_int_ppvoid_pvoid(AttachCurrentThread),
new pf_int(DetachCurrentThread),
new pf_int_ppvoid_int(GetEnv),
new pf_int_ppvoid_pvoid(AttachCurrentThreadAsDaemon)
};
2004-09-09 15:17:55 +04:00
static JavaVM()
{
JNI.jvmCreated = true;
pJavaVM = (JavaVM*)(void*)JniMem.Alloc(IntPtr.Size * (1 + vtableDelegates.Length));
pJavaVM->vtable = &pJavaVM->firstVtableEntry;
for(int i = 0; i < vtableDelegates.Length; i++)
{
pJavaVM->vtable[i] = JniHelper.ikvm_MarshalDelegate(vtableDelegates[i]);
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jint DestroyJavaVM(JavaVM* pJVM)
2004-08-30 19:56:23 +04:00
{
2005-02-02 18:11:26 +03:00
if(JNI.jvmDestroyed)
{
return JNIEnv.JNI_ERR;
}
JNI.jvmDestroyed = true;
2004-11-29 16:58:21 +03:00
JVM.Library.jniWaitUntilLastThread();
2005-02-02 18:11:26 +03:00
return JNIEnv.JNI_OK;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jint AttachCurrentThread(JavaVM* pJVM, void **penv, void *args)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return AttachCurrentThreadImpl(pJVM, penv, (JavaVMAttachArgs*)args, false);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jint AttachCurrentThreadImpl(JavaVM* pJVM, void** penv, JavaVMAttachArgs* pAttachArgs, bool asDaemon)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(pAttachArgs != null)
2004-08-30 19:56:23 +04:00
{
2005-02-02 18:11:26 +03:00
if(!JNI.IsSupportedJniVersion(pAttachArgs->version) || pAttachArgs->version == JNIEnv.JNI_VERSION_1_1)
2004-09-09 15:17:55 +04:00
{
*penv = null;
return JNIEnv.JNI_EVERSION;
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
JNIEnv* p = TlsHack.pJNIEnv;
if(p != null)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
*penv = p;
return JNIEnv.JNI_OK;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
// NOTE if we're here, it is *very* likely that the thread was created by native code and not by managed code,
// but it's not impossible that the thread started life as a managed thread and if it did the changes to the
// thread we're making are somewhat dubious.
2005-02-02 18:11:26 +03:00
System.Threading.Thread.CurrentThread.IsBackground = asDaemon;
2004-09-09 15:17:55 +04:00
if(pAttachArgs != null)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(pAttachArgs->name != null && System.Threading.Thread.CurrentThread.Name == null)
{
2005-02-02 18:11:26 +03:00
try
{
System.Threading.Thread.CurrentThread.Name = JNIEnv.StringFromUTF8(pAttachArgs->name);
2005-02-02 18:11:26 +03:00
}
catch(InvalidOperationException)
{
// someone beat us to it...
}
2004-09-09 15:17:55 +04:00
}
// NOTE we're calling UnwrapRef on a null reference, but that's OK because group is a global reference
object threadGroup = p->UnwrapRef(pAttachArgs->group);
if(threadGroup != null)
{
2005-02-02 18:11:26 +03:00
JVM.Library.setThreadGroup(threadGroup);
2004-09-09 15:17:55 +04:00
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
*penv = JNIEnv.CreateJNIEnv();
return JNIEnv.JNI_OK;
2003-01-07 14:40:11 +03:00
}
2003-01-17 17:34:33 +03:00
2004-09-09 15:17:55 +04:00
internal static jint DetachCurrentThread(JavaVM* pJVM)
2003-01-07 14:40:11 +03:00
{
2004-09-09 15:17:55 +04:00
if(TlsHack.pJNIEnv == null)
2003-01-07 14:40:11 +03:00
{
2005-02-02 18:11:26 +03:00
// the JDK allows detaching from an already detached thread
return JNIEnv.JNI_OK;
2003-01-07 14:40:11 +03:00
}
2004-09-09 15:17:55 +04:00
// TODO if we set Thread.IsBackground to false when we attached, now might be a good time to set it back to true.
JNIEnv.FreeJNIEnv();
2004-11-29 16:58:21 +03:00
JVM.Library.jniDetach();
2004-09-09 15:17:55 +04:00
return JNIEnv.JNI_OK;
2003-01-07 14:40:11 +03:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jint GetEnv(JavaVM* pJVM, void **penv, jint version)
2004-08-30 19:56:23 +04:00
{
2005-02-02 18:11:26 +03:00
if(JNI.IsSupportedJniVersion(version))
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
JNIEnv* p = TlsHack.pJNIEnv;
if(p != null)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
*penv = p;
return JNIEnv.JNI_OK;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
*penv = null;
return JNIEnv.JNI_EDETACHED;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
*penv = null;
return JNIEnv.JNI_EVERSION;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jint AttachCurrentThreadAsDaemon(JavaVM* pJVM, void **penv, void *args)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return AttachCurrentThreadImpl(pJVM, penv, (JavaVMAttachArgs*)args, true);
2004-08-30 19:56:23 +04:00
}
}
2004-09-09 15:17:55 +04:00
[StructLayout(LayoutKind.Sequential)]
unsafe struct JNIEnv
{
2005-02-02 18:11:26 +03:00
// NOTE LOCAL_REF_BUCKET_SIZE must be at least 512 to allow all method arguments to fit
// in a single slot, because Frame.MakeLocalRef() doesn't support spilling into a new bucket
2004-09-09 15:17:55 +04:00
internal const int LOCAL_REF_SHIFT = 10;
internal const int LOCAL_REF_BUCKET_SIZE = (1 << LOCAL_REF_SHIFT);
internal const int LOCAL_REF_MASK = (LOCAL_REF_BUCKET_SIZE - 1);
internal const int JNI_OK = 0;
internal const int JNI_ERR = -1;
internal const int JNI_EDETACHED = -2;
internal const int JNI_EVERSION = -3;
internal const int JNI_COMMIT = 1;
internal const int JNI_ABORT = 2;
internal const int JNI_VERSION_1_1 = 0x00010001;
internal const int JNI_VERSION_1_2 = 0x00010002;
internal const int JNI_VERSION_1_4 = 0x00010004;
internal const sbyte JNI_TRUE = 1;
internal const sbyte JNI_FALSE = 0;
internal void* vtable;
internal GCHandle localRefs;
internal int localRefSlot;
internal IntPtr pendingException;
internal RuntimeMethodHandle currentMethod;
2005-01-05 15:56:37 +03:00
internal GCHandle classLoader;
2005-09-01 11:34:53 +04:00
internal GCHandle criticalArrayHandle1;
internal GCHandle criticalArrayHandle2;
2004-09-09 15:17:55 +04:00
private static LocalDataStoreSlot cleanupHelperDataSlot = System.Threading.Thread.AllocateDataSlot();
unsafe class JNIEnvCleanupHelper
{
private JNIEnv* pJNIEnv;
internal JNIEnvCleanupHelper(JNIEnv* pJNIEnv)
{
this.pJNIEnv = pJNIEnv;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
~JNIEnvCleanupHelper()
{
2005-05-02 11:53:42 +04:00
// NOTE don't clean up when we're being unloaded (we'll get cleaned up anyway and because
// of the unorderedness of the finalization process native code could still be run after
// we run).
// NOTE when we're not the default AppDomain and we're being unloaded,
// we're leaking the JNIEnv (but since JNI outside of the default AppDomain isn't currently supported,
// I can live with that).
2005-05-02 12:12:36 +04:00
if(!Environment.HasShutdownStarted)
2005-05-02 11:53:42 +04:00
{
if(pJNIEnv->localRefs.IsAllocated)
{
pJNIEnv->localRefs.Free();
}
if(pJNIEnv->classLoader.IsAllocated)
{
pJNIEnv->classLoader.Free();
}
2005-09-01 11:34:53 +04:00
if(pJNIEnv->criticalArrayHandle1.IsAllocated)
{
pJNIEnv->criticalArrayHandle1.Free();
}
if(pJNIEnv->criticalArrayHandle2.IsAllocated)
{
pJNIEnv->criticalArrayHandle2.Free();
}
2005-05-02 11:53:42 +04:00
JniMem.Free((IntPtr)(void*)pJNIEnv);
}
2004-09-09 15:17:55 +04:00
}
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static JNIEnv* CreateJNIEnv()
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
JNIEnv* pJNIEnv = TlsHack.pJNIEnv = (JNIEnv*)JniMem.Alloc(sizeof(JNIEnv));
2005-05-02 12:12:36 +04:00
// don't touch the LocalDataStore slot when we're being unloaded
// (it may have been finalized already)
if(!Environment.HasShutdownStarted)
{
System.Threading.Thread.SetData(cleanupHelperDataSlot, new JNIEnvCleanupHelper(pJNIEnv));
}
2004-09-09 15:17:55 +04:00
pJNIEnv->vtable = VtableBuilder.vtable;
object[][] localRefs = new object[32][];
localRefs[0] = new object[JNIEnv.LOCAL_REF_BUCKET_SIZE];
// stuff something in the first entry to make sure we don't hand out a zero handle
// (a zero handle corresponds to a null reference)
localRefs[0][0] = "";
pJNIEnv->localRefs = GCHandle.Alloc(localRefs);
pJNIEnv->localRefSlot = 0;
pJNIEnv->pendingException = IntPtr.Zero;
pJNIEnv->currentMethod = new RuntimeMethodHandle();
2005-01-05 15:56:37 +03:00
pJNIEnv->classLoader = GCHandle.Alloc(null);
2005-09-01 11:34:53 +04:00
pJNIEnv->criticalArrayHandle1 = GCHandle.Alloc(null, GCHandleType.Pinned);
pJNIEnv->criticalArrayHandle2 = GCHandle.Alloc(null, GCHandleType.Pinned);
2004-09-09 15:17:55 +04:00
return pJNIEnv;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void FreeJNIEnv()
2004-08-30 19:56:23 +04:00
{
2005-05-02 11:53:42 +04:00
// don't touch the LocalDataStore slot when we're being unloaded
// (it may have been finalized already)
2005-05-02 12:12:36 +04:00
if(!Environment.HasShutdownStarted)
2005-05-02 11:53:42 +04:00
{
// the cleanup helper will eventually free the JNIEnv
System.Threading.Thread.SetData(cleanupHelperDataSlot, null);
}
2004-09-09 15:17:55 +04:00
TlsHack.pJNIEnv = null;
2004-08-30 19:56:23 +04:00
}
internal static string StringFromOEM(byte* psz)
{
for(int i = 0;; i++)
{
if(psz[i] == 0)
{
int oem = System.Globalization.CultureInfo.CurrentCulture.TextInfo.OEMCodePage;
return new String((sbyte*)psz, 0, i, Encoding.GetEncoding(oem));
}
}
}
2004-09-09 15:17:55 +04:00
internal static string StringFromUTF8(byte* psz)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
// Sun's modified UTF8 encoding is not compatible with System.Text.Encoding.UTF8,
// so we need to roll our own
int len = 0;
bool hasNonAscii = false;
while(psz[len] != 0)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
hasNonAscii |= psz[len] >= 128;
len++;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
if(!hasNonAscii)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
// optimize the common case of 7-bit ASCII
return new String((sbyte*)psz);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
StringBuilder sb = new StringBuilder(len);
for(int i = 0; i < len; i++)
{
int c = *psz++;
int char2, char3;
switch(c >> 4)
{
case 12:
case 13:
char2 = *psz++;
i++;
c = (((c & 0x1F) << 6) | (char2 & 0x3F));
break;
case 14:
char2 = *psz++;
char3 = *psz++;
i++;
i++;
c = ((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | (char3 & 0x3F);
break;
}
sb.Append((char)c);
}
return sb.ToString();
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
private static int StringUTF8Length(string s)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
int len = 0;
for(int i = 0; i < s.Length; i++)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
char ch = s[i];
if((ch != 0) && (ch <= 0x7F))
{
len++;
}
else if(ch <= 0x7FF)
{
len += 2;
}
else
{
len += 3;
}
}
return len;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
// this method returns a simplified method argument descriptor.
// some examples:
// "()V" -> ""
// "(ILjava.lang.String;)I" -> "IL"
// "([Ljava.lang.String;)V" -> "L"
private static string GetMethodArgList(IntPtr cookie)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
StringBuilder sb = new StringBuilder();
string s = MethodWrapper.FromCookie(cookie).Signature;
for(int i = 1;; i++)
{
switch(s[i])
{
case '[':
while(s[i] == '[') i++;
if(s[i] == 'L')
{
while(s[i] != ';') i++;
}
sb.Append('L');
break;
case 'L':
while(s[i] != ';') i++;
sb.Append('L');
break;
case ')':
return sb.ToString();
default:
sb.Append(s[i]);
break;
}
}
}
catch
{
Debug.Assert(false);
throw;
}
2004-09-05 13:37:58 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jint GetMethodArgs(JNIEnv* pEnv, IntPtr method, byte* sig)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
string s = GetMethodArgList(method);
for(int i = 0; i < s.Length; i++)
{
sig[i] = (byte)s[i];
}
return s.Length;
2004-09-05 13:37:58 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jint GetVersion(JNIEnv* pEnv)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return JNI_VERSION_1_4;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jclass DefineClass(JNIEnv* pEnv, byte* name, jobject loader, jbyte* pbuf, jint length)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
try
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
byte[] buf = new byte[length];
Marshal.Copy((IntPtr)(void*)pbuf, buf, 0, length);
// TODO what should the protection domain be?
// NOTE I'm assuming name is platform encoded (as opposed to UTF-8), but the Sun JVM only seems to work for ASCII.
return pEnv->MakeLocalRef(IKVM.NativeCode.java.lang.VMClassLoader.defineClassImpl(pEnv->UnwrapRef(loader), name != null ? StringFromOEM(name) : null, buf, 0, buf.Length, null));
2004-09-05 13:37:58 +04:00
}
2004-09-09 15:17:55 +04:00
catch(Exception x)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
SetPendingException(pEnv, x);
return IntPtr.Zero;
2004-09-05 13:37:58 +04:00
}
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
private static ClassLoaderWrapper FindNativeMethodClassLoader(JNIEnv* pEnv)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(pEnv->currentMethod.Value != IntPtr.Zero)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
MethodBase mb = MethodBase.GetMethodFromHandle(pEnv->currentMethod);
2006-08-14 11:57:03 +04:00
return ClassLoaderWrapper.GetWrapperFromType(mb.DeclaringType).GetClassLoader();
2004-09-05 13:37:58 +04:00
}
2005-01-05 15:56:37 +03:00
if(pEnv->classLoader.Target != null)
{
return (ClassLoaderWrapper)pEnv->classLoader.Target;
}
2006-08-14 11:57:03 +04:00
return ClassLoaderWrapper.GetBootstrapClassLoader();
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
2005-02-02 18:11:26 +03:00
internal static jclass FindClass(JNIEnv* pEnv, byte* pszName)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
string name = StringFromOEM(pszName);
2005-02-02 18:11:26 +03:00
// don't allow dotted names!
if(name.IndexOf('.') >= 0)
{
SetPendingException(pEnv, JavaException.NoClassDefFoundError(name));
return IntPtr.Zero;
}
// spec doesn't say it, but Sun allows signature format class names (but not for primitives)
if(name.StartsWith("L") && name.EndsWith(";"))
{
name = name.Substring(1, name.Length - 2);
}
2005-08-25 11:46:57 +04:00
TypeWrapper wrapper = FindNativeMethodClassLoader(pEnv).LoadClassByDottedNameFast(name.Replace('/', '.'));
if(wrapper == null)
{
SetPendingException(pEnv, JavaException.NoClassDefFoundError(name));
return IntPtr.Zero;
}
2004-09-09 15:17:55 +04:00
wrapper.Finish();
// spec doesn't say it, but Sun runs the static initializer
wrapper.RunClassInit();
2004-12-21 17:59:29 +03:00
return pEnv->MakeLocalRef(wrapper.ClassObject);
}
2004-09-09 15:17:55 +04:00
catch(Exception x)
{
2005-02-02 18:11:26 +03:00
if(x is RetargetableJavaException)
{
x = ((RetargetableJavaException)x).ToJava();
}
2004-09-09 15:17:55 +04:00
SetPendingException(pEnv, x);
return IntPtr.Zero;
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jmethodID FromReflectedMethod(JNIEnv* pEnv, jobject method)
2004-08-30 19:56:23 +04:00
{
2004-11-29 16:58:21 +03:00
return ((MethodWrapper)JVM.Library.getWrapperFromMethodOrConstructor(pEnv->UnwrapRef(method))).Cookie;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jfieldID FromReflectedField(JNIEnv* pEnv, jobject field)
2004-08-30 19:56:23 +04:00
{
2004-11-29 16:58:21 +03:00
return ((FieldWrapper)JVM.Library.getWrapperFromField(pEnv->UnwrapRef(field))).Cookie;
2004-08-30 19:56:23 +04:00
}
2004-09-05 13:37:58 +04:00
2005-05-17 17:18:16 +04:00
internal static jobject ToReflectedMethod(JNIEnv* pEnv, jclass clazz_ignored, jmethodID method, jboolean isStatic)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
MethodWrapper mw = MethodWrapper.FromCookie(method);
2004-12-21 17:59:29 +03:00
object clazz = mw.DeclaringType.ClassObject;
2004-09-09 15:17:55 +04:00
if(mw.Name == "<init>")
{
2004-11-29 16:58:21 +03:00
return pEnv->MakeLocalRef(JVM.Library.newConstructor(clazz, mw));
2004-09-09 15:17:55 +04:00
}
else
{
2004-11-29 16:58:21 +03:00
return pEnv->MakeLocalRef(JVM.Library.newMethod(clazz, mw));
2004-09-09 15:17:55 +04:00
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jclass GetSuperclass(JNIEnv* pEnv, jclass sub)
2004-08-30 19:56:23 +04:00
{
2006-03-27 17:59:59 +04:00
TypeWrapper wrapper = TypeWrapper.FromClass(pEnv->UnwrapRef(sub)).BaseTypeWrapper;
2004-12-21 17:59:29 +03:00
return pEnv->MakeLocalRef(wrapper == null ? null : wrapper.ClassObject);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jboolean IsAssignableFrom(JNIEnv* pEnv, jclass sub, jclass super)
{
2006-03-27 17:59:59 +04:00
TypeWrapper w1 = TypeWrapper.FromClass(pEnv->UnwrapRef(sub));
TypeWrapper w2 = TypeWrapper.FromClass(pEnv->UnwrapRef(super));
2004-09-09 15:17:55 +04:00
return w1.IsAssignableTo(w2) ? JNI_TRUE : JNI_FALSE;
2004-08-30 19:56:23 +04:00
}
2005-05-17 17:18:16 +04:00
internal static jobject ToReflectedField(JNIEnv* pEnv, jclass clazz_ignored, jfieldID field, jboolean isStatic)
2004-09-09 15:17:55 +04:00
{
FieldWrapper fw = FieldWrapper.FromCookie(field);
2004-12-21 17:59:29 +03:00
object clazz = fw.DeclaringType.ClassObject;
2004-11-29 16:58:21 +03:00
return pEnv->MakeLocalRef(JVM.Library.newField(clazz, fw));
2004-09-09 15:17:55 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
private static void SetPendingException(JNIEnv* pEnv, Exception x)
{
DeleteLocalRef(pEnv, pEnv->pendingException);
2006-08-17 11:33:38 +04:00
pEnv->pendingException = x == null ? IntPtr.Zero : pEnv->MakeLocalRef(JVM.Library.mapException(x));
2004-09-09 15:17:55 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jint Throw(JNIEnv* pEnv, jthrowable throwable)
{
DeleteLocalRef(pEnv, pEnv->pendingException);
pEnv->pendingException = NewLocalRef(pEnv, throwable);
return JNI_OK;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jint ThrowNew(JNIEnv* pEnv, jclass clazz, byte* msg)
2004-08-30 19:56:23 +04:00
{
2006-03-27 17:59:59 +04:00
TypeWrapper wrapper = TypeWrapper.FromClass(pEnv->UnwrapRef(clazz));
2005-01-03 11:26:21 +03:00
MethodWrapper mw = wrapper.GetMethodWrapper("<init>", "(Ljava.lang.String;)V", false);
2004-08-30 19:56:23 +04:00
if(mw != null)
{
2004-09-09 15:17:55 +04:00
jint rc;
Exception exception;
try
{
wrapper.Finish();
exception = (Exception)mw.Invoke(null, new object[] { StringFromOEM(msg) }, false);
2004-09-09 15:17:55 +04:00
rc = JNI_OK;
}
2004-12-21 17:59:29 +03:00
catch(RetargetableJavaException x)
{
exception = x.ToJava();
rc = JNI_ERR;
}
2004-09-09 15:17:55 +04:00
catch(Exception x)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
exception = x;
rc = JNI_ERR;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
SetPendingException(pEnv, exception);
return rc;
}
else
{
SetPendingException(pEnv, JavaException.NoSuchMethodError("<init>(Ljava.lang.String;)V"));
return JNI_ERR;
2004-08-30 19:56:23 +04:00
}
}
2004-09-09 15:17:55 +04:00
internal static jthrowable ExceptionOccurred(JNIEnv* pEnv)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return NewLocalRef(pEnv, pEnv->pendingException);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void ExceptionDescribe(JNIEnv* pEnv)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
Exception x = (Exception)pEnv->UnwrapRef(pEnv->pendingException);
if(x != null)
{
SetPendingException(pEnv, null);
try
{
2004-11-29 16:58:21 +03:00
JVM.Library.printStackTrace(x);
2004-09-09 15:17:55 +04:00
}
catch(Exception ex)
{
Debug.Assert(false, ex.ToString());
}
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void ExceptionClear(JNIEnv* pEnv)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
DeleteLocalRef(pEnv, pEnv->pendingException);
pEnv->pendingException = IntPtr.Zero;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void FatalError(JNIEnv* pEnv, byte* msg)
2004-08-30 19:56:23 +04:00
{
Console.Error.WriteLine("FATAL ERROR in native method: {0}", msg == null ? "(null)" : StringFromOEM(msg));
Console.Error.WriteLine(new StackTrace(1, true));
Environment.Exit(1);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jint PushLocalFrame(JNIEnv* pEnv, jint capacity)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
object[][] localRefs = pEnv->GetLocalRefs();
pEnv->localRefSlot += 2;
if(pEnv->localRefSlot >= localRefs.Length)
{
object[][] tmp = new object[localRefs.Length * 2][];
Array.Copy(localRefs, 0, tmp, 0, localRefs.Length);
pEnv->localRefs.Target = localRefs = tmp;
}
// we use a null slot to mark the fact that we used PushLocalFrame
localRefs[pEnv->localRefSlot - 1] = null;
if(localRefs[pEnv->localRefSlot] == null)
{
2005-02-02 18:11:26 +03:00
// we can't use capacity directly, because the array length must be a power of two
// and it can't be bigger than LOCAL_REF_BUCKET_SIZE
int r = 1;
capacity = Math.Min(capacity, LOCAL_REF_BUCKET_SIZE);
while(r < capacity)
{
r *= 2;
}
localRefs[pEnv->localRefSlot] = new object[r];
2004-09-09 15:17:55 +04:00
}
return JNI_OK;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jobject PopLocalFrame(JNIEnv* pEnv, jobject result)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
object res = pEnv->UnwrapRef(result);
object[][] localRefs = pEnv->GetLocalRefs();
while(localRefs[pEnv->localRefSlot] != null)
{
localRefs[pEnv->localRefSlot] = null;
pEnv->localRefSlot--;
}
pEnv->localRefSlot--;
return pEnv->MakeLocalRef(res);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jobject NewGlobalRef(JNIEnv* pEnv, jobject obj)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
object o = pEnv->UnwrapRef(obj);
if(o == null)
{
return IntPtr.Zero;
}
lock(GlobalRefs.globalRefs)
{
int index = GlobalRefs.globalRefs.IndexOf(null);
if(index >= 0)
{
GlobalRefs.globalRefs[index] = o;
}
else
{
index = GlobalRefs.globalRefs.Add(o);
}
return (IntPtr)(-(index + 1));
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void DeleteGlobalRef(JNIEnv* pEnv, jobject obj)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
int i = obj.ToInt32();
if(i < 0)
{
lock(GlobalRefs.globalRefs)
{
GlobalRefs.globalRefs[(-i) - 1] = null;
}
return;
}
if(i > 0)
{
Debug.Assert(false, "Local ref passed to DeleteGlobalRef");
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal object[][] GetLocalRefs()
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return (object[][])localRefs.Target;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void DeleteLocalRef(JNIEnv* pEnv, jobject obj)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
int i = obj.ToInt32();
if(i > 0)
{
object[][] localRefs = pEnv->GetLocalRefs();
localRefs[i >> LOCAL_REF_SHIFT][i & LOCAL_REF_MASK] = null;
return;
}
if(i < 0)
{
Debug.Assert(false, "bogus localref in DeleteLocalRef");
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jboolean IsSameObject(JNIEnv* pEnv, jobject obj1, jobject obj2)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return pEnv->UnwrapRef(obj1) == pEnv->UnwrapRef(obj2) ? JNI_TRUE : JNI_FALSE;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jobject NewLocalRef(JNIEnv* pEnv, jobject obj)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return pEnv->MakeLocalRef(pEnv->UnwrapRef(obj));
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jint EnsureLocalCapacity(JNIEnv* pEnv, jint capacity)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
// since we can dynamically grow the local ref table, we'll just return success for any number
return JNI_OK;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jobject AllocObject(JNIEnv* pEnv, jclass clazz)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
2006-03-27 17:59:59 +04:00
TypeWrapper wrapper = TypeWrapper.FromClass(pEnv->UnwrapRef(clazz));
2004-10-19 17:43:55 +04:00
if(wrapper.IsAbstract)
2004-09-09 15:17:55 +04:00
{
SetPendingException(pEnv, JavaException.InstantiationException(wrapper.Name));
return IntPtr.Zero;
}
wrapper.Finish();
return pEnv->MakeLocalRef(System.Runtime.Serialization.FormatterServices.GetUninitializedObject(wrapper.TypeAsBaseType));
}
2004-12-21 17:59:29 +03:00
catch(RetargetableJavaException x)
{
SetPendingException(pEnv, x.ToJava());
return IntPtr.Zero;
}
2004-09-09 15:17:55 +04:00
catch(Exception x)
{
SetPendingException(pEnv, x);
return IntPtr.Zero;
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
[StructLayout(LayoutKind.Explicit)]
internal struct jvalue
{
[FieldOffset(0)]
public jboolean z;
[FieldOffset(0)]
public jbyte b;
[FieldOffset(0)]
public jchar c;
[FieldOffset(0)]
public jshort s;
[FieldOffset(0)]
public jint i;
[FieldOffset(0)]
public jlong j;
[FieldOffset(0)]
public jfloat f;
[FieldOffset(0)]
public jdouble d;
[FieldOffset(0)]
public jobject l;
}
private static object InvokeHelper(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue *args, bool nonVirtual)
{
string sig = GetMethodArgList(methodID);
object[] argarray = new object[sig.Length];
for(int i = 0; i < sig.Length; i++)
{
switch(sig[i])
{
case 'Z':
argarray[i] = args[i].z != JNI_FALSE;
break;
case 'B':
argarray[i] = args[i].b;
break;
case 'C':
argarray[i] = (char)args[i].c;
break;
case 'S':
argarray[i] = args[i].s;
break;
case 'I':
argarray[i] = args[i].i;
break;
case 'J':
argarray[i] = args[i].j;
break;
case 'F':
argarray[i] = args[i].f;
break;
case 'D':
argarray[i] = args[i].d;
break;
case 'L':
argarray[i] = pEnv->UnwrapRef(args[i].l);
break;
}
}
try
{
return MethodWrapper.FromCookie(methodID).Invoke(pEnv->UnwrapRef(obj), argarray, nonVirtual);
}
catch(Exception x)
{
2005-02-02 18:11:26 +03:00
if(ClassLoaderWrapper.LoadClassCritical("java.lang.reflect.InvocationTargetException").TypeAsExceptionType.IsInstanceOfType(x))
2004-09-27 14:17:34 +04:00
{
x = x.InnerException;
}
2006-08-17 11:33:38 +04:00
SetPendingException(pEnv, JVM.Library.mapException(x));
2004-09-09 15:17:55 +04:00
return null;
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jobject NewObjectA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return pEnv->MakeLocalRef(InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false));
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jclass GetObjectClass(JNIEnv* pEnv, jobject obj)
2004-08-30 19:56:23 +04:00
{
2006-08-17 11:33:38 +04:00
return pEnv->MakeLocalRef(IKVM.NativeCode.ikvm.runtime.Util.getClassFromObject(pEnv->UnwrapRef(obj)));
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jboolean IsInstanceOf(JNIEnv* pEnv, jobject obj, jclass clazz)
{
2005-02-02 18:11:26 +03:00
// NOTE if clazz is an interface, this is still the right thing to do
// (i.e. if the object implements the interface, we return true)
2006-08-17 11:33:38 +04:00
object objClass = IKVM.NativeCode.ikvm.runtime.Util.getClassFromObject(pEnv->UnwrapRef(obj));
2006-03-27 17:59:59 +04:00
TypeWrapper w1 = TypeWrapper.FromClass(pEnv->UnwrapRef(clazz));
TypeWrapper w2 = TypeWrapper.FromClass(objClass);
2004-09-09 15:17:55 +04:00
return w2.IsAssignableTo(w1) ? JNI_TRUE : JNI_FALSE;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
private static jmethodID FindMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig, bool isstatic)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
try
2004-08-30 19:56:23 +04:00
{
2006-03-27 17:59:59 +04:00
TypeWrapper wrapper = TypeWrapper.FromClass(pEnv->UnwrapRef(clazz));
2004-09-09 15:17:55 +04:00
wrapper.Finish();
2005-02-16 14:20:43 +03:00
string methodsig = StringFromUTF8(sig);
// don't allow dotted names!
if(methodsig.IndexOf('.') < 0)
2004-08-30 19:56:23 +04:00
{
2005-02-16 14:20:43 +03:00
MethodWrapper mw = wrapper.GetMethodWrapper(StringFromUTF8(name), methodsig.Replace('/', '.'), true);
if(mw != null)
2004-09-09 15:17:55 +04:00
{
2005-02-16 14:20:43 +03:00
if(mw.IsStatic == isstatic)
{
mw.Link();
return mw.Cookie;
}
2004-09-09 15:17:55 +04:00
}
2004-08-30 19:56:23 +04:00
}
2005-01-03 11:26:21 +03:00
SetPendingException(pEnv, JavaException.NoSuchMethodError("{0}{1}", StringFromUTF8(name), StringFromUTF8(sig).Replace('/', '.')));
2004-08-30 19:56:23 +04:00
}
2004-12-21 17:59:29 +03:00
catch(RetargetableJavaException x)
{
SetPendingException(pEnv, x.ToJava());
}
2004-09-09 15:17:55 +04:00
catch(Exception x)
{
SetPendingException(pEnv, x);
}
return IntPtr.Zero;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jmethodID GetMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return FindMethodID(pEnv, clazz, name, sig, false);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jobject CallObjectMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return pEnv->MakeLocalRef(InvokeHelper(pEnv, obj, methodID, args, false));
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jboolean CallBooleanMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
object o = InvokeHelper(pEnv, obj, methodID, args, false);
if(o != null)
{
return ((bool)o) ? JNI_TRUE : JNI_FALSE;
}
return JNI_FALSE;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jbyte CallByteMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
object o = InvokeHelper(pEnv, obj, methodID, args, false);
if(o != null)
{
2005-02-02 18:11:26 +03:00
return (jbyte)(byte)o;
2004-09-09 15:17:55 +04:00
}
return 0;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jchar CallCharMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, false);
if(o != null)
{
return (jchar)(char)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jshort CallShortMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, false);
if(o != null)
{
return (jshort)(short)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jint CallIntMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, false);
if(o != null)
{
return (jint)(int)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jlong CallLongMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, false);
if(o != null)
{
return (jlong)(long)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jfloat CallFloatMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, false);
if(o != null)
{
return (jfloat)(float)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jdouble CallDoubleMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, false);
if(o != null)
{
return (jdouble)(double)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void CallVoidMethodA(JNIEnv* pEnv, jobject obj, jmethodID methodID, jvalue* args)
{
InvokeHelper(pEnv, obj, methodID, args, false);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jobject CallNonvirtualObjectMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
{
return pEnv->MakeLocalRef(InvokeHelper(pEnv, obj, methodID, args, true));
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jboolean CallNonvirtualBooleanMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, true);
if(o != null)
{
return ((bool)o) ? JNI_TRUE : JNI_FALSE;
}
return JNI_FALSE;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jbyte CallNonvirtualByteMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, true);
if(o != null)
{
2005-02-02 18:11:26 +03:00
return (jbyte)(byte)o;
2004-09-09 15:17:55 +04:00
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jchar CallNonvirtualCharMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, true);
if(o != null)
{
return (jchar)(char)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jshort CallNonvirtualShortMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, true);
if(o != null)
{
return (jshort)(short)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jint CallNonvirtualIntMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, true);
if(o != null)
{
return (jint)(int)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jlong CallNonvirtualLongMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, true);
if(o != null)
{
return (jlong)(long)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jfloat CallNonvirtualFloatMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, true);
if(o != null)
{
return (jfloat)(float)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jdouble CallNonvirtualDoubleMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
{
object o = InvokeHelper(pEnv, obj, methodID, args, true);
if(o != null)
{
return (jdouble)(double)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void CallNonvirtualVoidMethodA(JNIEnv* pEnv, jobject obj, jclass clazz, jmethodID methodID, jvalue* args)
{
InvokeHelper(pEnv, obj, methodID, args, true);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
private static jfieldID FindFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig, bool isstatic)
{
try
{
2006-03-27 17:59:59 +04:00
TypeWrapper wrapper = TypeWrapper.FromClass(pEnv->UnwrapRef(clazz));
2004-09-09 15:17:55 +04:00
wrapper.Finish();
2005-02-16 14:20:43 +03:00
string fieldsig = StringFromUTF8(sig);
// don't allow dotted names!
if(fieldsig.IndexOf('.') < 0)
2004-09-09 15:17:55 +04:00
{
2005-02-16 14:20:43 +03:00
FieldWrapper fw = wrapper.GetFieldWrapper(StringFromUTF8(name), fieldsig.Replace('/', '.'));
if(fw != null)
2004-09-09 15:17:55 +04:00
{
2005-02-16 14:20:43 +03:00
if(fw.IsStatic == isstatic)
{
return fw.Cookie;
}
2004-09-09 15:17:55 +04:00
}
}
2006-10-19 10:12:48 +04:00
SetPendingException(pEnv, JavaException.NoSuchFieldError((isstatic ? "Static" : "Instance") + " field '" + StringFromUTF8(name) + "' with signature '" + fieldsig + "' not found in class '" + wrapper.Name + "'"));
2004-09-09 15:17:55 +04:00
}
2004-12-21 17:59:29 +03:00
catch(RetargetableJavaException x)
{
SetPendingException(pEnv, x.ToJava());
}
2004-09-09 15:17:55 +04:00
catch(Exception x)
{
SetPendingException(pEnv, x);
}
return IntPtr.Zero;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jfieldID GetFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
{
return FindFieldID(pEnv, clazz, name, sig, false);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
private static void SetFieldValue(jfieldID cookie, object obj, object val)
{
try
{
FieldWrapper.FromCookie(cookie).SetValue(obj, val);
}
catch
{
Debug.Assert(false);
throw;
}
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
private static object GetFieldValue(jfieldID cookie, object obj)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
return FieldWrapper.FromCookie(cookie).GetValue(obj);
}
catch
{
Debug.Assert(false);
throw;
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jobject GetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return pEnv->MakeLocalRef(GetFieldValue(fieldID, pEnv->UnwrapRef(obj)));
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jboolean GetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return ((bool)GetFieldValue(fieldID, pEnv->UnwrapRef(obj))) ? JNI_TRUE : JNI_FALSE;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jbyte GetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2004-08-30 19:56:23 +04:00
{
2005-02-02 18:11:26 +03:00
return (jbyte)(byte)GetFieldValue(fieldID, pEnv->UnwrapRef(obj));
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jchar GetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return (jchar)(char)GetFieldValue(fieldID, pEnv->UnwrapRef(obj));
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jshort GetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return (jshort)(short)GetFieldValue(fieldID, pEnv->UnwrapRef(obj));
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jint GetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return (jint)(int)GetFieldValue(fieldID, pEnv->UnwrapRef(obj));
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jlong GetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return (jlong)(long)GetFieldValue(fieldID, pEnv->UnwrapRef(obj));
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jfloat GetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{
return (jfloat)(float)GetFieldValue(fieldID, pEnv->UnwrapRef(obj));
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jdouble GetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID)
{
return (jdouble)(double)GetFieldValue(fieldID, pEnv->UnwrapRef(obj));
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetObjectField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jobject val)
{
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), pEnv->UnwrapRef(val));
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetBooleanField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jboolean val)
{
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), val != JNI_FALSE);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetByteField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jbyte val)
{
2005-02-02 18:11:26 +03:00
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (byte)val);
2004-09-09 15:17:55 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetCharField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jchar val)
{
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (char)val);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetShortField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jshort val)
{
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (short)val);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetIntField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jint val)
{
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (int)val);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetLongField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jlong val)
{
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (long)val);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetFloatField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jfloat val)
{
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (float)val);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetDoubleField(JNIEnv* pEnv, jobject obj, jfieldID fieldID, jdouble val)
{
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (double)val);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jmethodID GetStaticMethodID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
{
return FindMethodID(pEnv, clazz, name, sig, true);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jobject CallStaticObjectMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
{
return pEnv->MakeLocalRef(InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false));
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jboolean CallStaticBooleanMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
{
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
if(o != null)
{
return ((bool)o) ? JNI_TRUE : JNI_FALSE;
}
return JNI_FALSE;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jbyte CallStaticByteMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
{
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
if(o != null)
{
2005-02-02 18:11:26 +03:00
return (jbyte)(byte)o;
2004-09-09 15:17:55 +04:00
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jchar CallStaticCharMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
{
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
if(o != null)
{
return (jchar)(char)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jshort CallStaticShortMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
{
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
if(o != null)
{
return (jshort)(short)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jint CallStaticIntMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
{
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
if(o != null)
{
return (jint)(int)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jlong CallStaticLongMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
{
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
if(o != null)
{
return (jlong)(long)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jfloat CallStaticFloatMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
{
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
if(o != null)
{
return (jfloat)(float)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jdouble CallStaticDoubleMethodA(JNIEnv* pEnv, jclass clazz, jmethodID methodID, jvalue *args)
{
object o = InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
if(o != null)
{
return (jdouble)(double)o;
}
return 0;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void CallStaticVoidMethodA(JNIEnv* pEnv, jclass cls, jmethodID methodID, jvalue * args)
{
InvokeHelper(pEnv, IntPtr.Zero, methodID, args, false);
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jfieldID GetStaticFieldID(JNIEnv* pEnv, jclass clazz, byte* name, byte* sig)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return FindFieldID(pEnv, clazz, name, sig, true);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jobject GetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{
return pEnv->MakeLocalRef(GetFieldValue(fieldID, null));
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jboolean GetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{
return ((bool)GetFieldValue(fieldID, null)) ? JNI_TRUE : JNI_FALSE;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jbyte GetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{
2005-02-02 18:11:26 +03:00
return (jbyte)(byte)GetFieldValue(fieldID, null);
2004-09-09 15:17:55 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jchar GetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{
return (jchar)(char)GetFieldValue(fieldID, null);
}
internal static jshort GetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{
return (jshort)(short)GetFieldValue(fieldID, null);
}
internal static jint GetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return (jint)(int)GetFieldValue(fieldID, null);
}
internal static jlong GetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{
return (jlong)(long)GetFieldValue(fieldID, null);
}
internal static jfloat GetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{
return (jfloat)(float)GetFieldValue(fieldID, null);
}
internal static jdouble GetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID)
{
return (jdouble)(double)GetFieldValue(fieldID, null);
}
internal static void SetStaticObjectField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jobject val)
{
SetFieldValue(fieldID, null, pEnv->UnwrapRef(val));
}
internal static void SetStaticBooleanField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jboolean val)
{
SetFieldValue(fieldID, null, val != JNI_FALSE);
}
internal static void SetStaticByteField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jbyte val)
{
2005-02-02 18:11:26 +03:00
SetFieldValue(fieldID, null, (byte)val);
2004-09-09 15:17:55 +04:00
}
internal static void SetStaticCharField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jchar val)
{
SetFieldValue(fieldID, null, (char)val);
}
internal static void SetStaticShortField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jshort val)
{
SetFieldValue(fieldID, null, (short)val);
}
internal static void SetStaticIntField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jint val)
{
SetFieldValue(fieldID, null, (int)val);
}
internal static void SetStaticLongField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jlong val)
{
SetFieldValue(fieldID, null, (long)val);
}
internal static void SetStaticFloatField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jfloat val)
{
SetFieldValue(fieldID, null, (float)val);
}
internal static void SetStaticDoubleField(JNIEnv* pEnv, jclass clazz, jfieldID fieldID, jdouble val)
{
SetFieldValue(fieldID, null, (double)val);
}
internal static jstring NewString(JNIEnv* pEnv, jchar* unicode, int len)
{
return pEnv->MakeLocalRef(new String((char*)unicode, 0, len));
}
internal static jint GetStringLength(JNIEnv* pEnv, jstring str)
{
return ((string)pEnv->UnwrapRef(str)).Length;
}
internal static jchar* GetStringChars(JNIEnv* pEnv, jstring str, jboolean* isCopy)
{
string s = (string)pEnv->UnwrapRef(str);
if(isCopy != null)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
*isCopy = JNI_TRUE;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
return (jchar*)(void*)Marshal.StringToHGlobalUni(s);
}
internal static void ReleaseStringChars(JNIEnv* pEnv, jstring str, jchar* chars)
{
Marshal.FreeHGlobal((IntPtr)(void*)chars);
}
internal static jobject NewStringUTF(JNIEnv* pEnv, byte* psz)
{
return pEnv->MakeLocalRef(StringFromUTF8(psz));
}
internal static jint GetStringUTFLength(JNIEnv* pEnv, jstring str)
{
return StringUTF8Length((string)pEnv->UnwrapRef(str));
}
internal static byte* GetStringUTFChars(JNIEnv* pEnv, jstring str, jboolean* isCopy)
{
string s = (string)pEnv->UnwrapRef(str);
byte* buf = (byte*)JniMem.Alloc(StringUTF8Length(s) + 1);
int j = 0;
for(int i = 0; i < s.Length; i++)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
char ch = s[i];
if((ch != 0) && (ch <= 0x7F))
{
buf[j++] = (byte)ch;
}
else if(ch <= 0x7FF)
{
buf[j++] = (byte)((ch >> 6) | 0xC0);
buf[j++] = (byte)((ch & 0x3F) | 0x80);
}
else
{
buf[j++] = (byte)((ch >> 12) | 0xE0);
buf[j++] = (byte)(((ch >> 6) & 0x3F) | 0x80);
buf[j++] = (byte)((ch & 0x3F) | 0x80);
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
buf[j] = 0;
if(isCopy != null)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
*isCopy = JNI_TRUE;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
return buf;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void ReleaseStringUTFChars(JNIEnv* pEnv, jstring str, byte* chars)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
JniMem.Free((IntPtr)(void*)chars);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jsize GetArrayLength(JNIEnv* pEnv, jarray array)
{
return ((Array)pEnv->UnwrapRef(array)).Length;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jobject NewObjectArray(JNIEnv* pEnv, jsize len, jclass clazz, jobject init)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
// we want to support (non-primitive) value types so we can't cast to object[]
2006-03-27 17:59:59 +04:00
Array array = Array.CreateInstance(TypeWrapper.FromClass(pEnv->UnwrapRef(clazz)).TypeAsArrayType, len);
2004-09-09 15:17:55 +04:00
object o = pEnv->UnwrapRef(init);
if(o != null)
{
for(int i = 0; i < array.Length; i++)
{
array.SetValue(o, i);
}
}
return pEnv->MakeLocalRef(array);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.NegativeArraySizeException());
return IntPtr.Zero;
}
catch(Exception x)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
SetPendingException(pEnv, x);
return IntPtr.Zero;
2004-08-30 19:56:23 +04:00
}
}
2004-09-09 15:17:55 +04:00
internal static jobject GetObjectArrayElement(JNIEnv* pEnv, jarray array, jsize index)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
// we want to support (non-primitive) value types so we can't cast to object[]
return pEnv->MakeLocalRef(((Array)pEnv->UnwrapRef(array)).GetValue(index));
}
catch(IndexOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
return IntPtr.Zero;
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void SetObjectArrayElement(JNIEnv* pEnv, jarray array, jsize index, jobject val)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
// we want to support (non-primitive) value types so we can't cast to object[]
((Array)pEnv->UnwrapRef(array)).SetValue(pEnv->UnwrapRef(val), index);
}
catch(IndexOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jbooleanArray NewBooleanArray(JNIEnv* pEnv, jsize len)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
return pEnv->MakeLocalRef(new bool[len]);
}
catch(Exception x)
{
SetPendingException(pEnv, x);
return IntPtr.Zero;
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jbyteArray NewByteArray(JNIEnv* pEnv, jsize len)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
2005-02-02 18:11:26 +03:00
return pEnv->MakeLocalRef(new byte[len]);
2004-09-09 15:17:55 +04:00
}
catch(Exception x)
{
SetPendingException(pEnv, x);
return IntPtr.Zero;
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jcharArray NewCharArray(JNIEnv* pEnv, jsize len)
{
try
{
return pEnv->MakeLocalRef(new char[len]);
}
catch(Exception x)
{
SetPendingException(pEnv, x);
return IntPtr.Zero;
}
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jshortArray NewShortArray(JNIEnv* pEnv, jsize len)
{
try
{
return pEnv->MakeLocalRef(new short[len]);
}
catch(Exception x)
{
SetPendingException(pEnv, x);
return IntPtr.Zero;
}
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jintArray NewIntArray(JNIEnv* pEnv, jsize len)
{
try
{
return pEnv->MakeLocalRef(new int[len]);
}
catch(Exception x)
{
SetPendingException(pEnv, x);
return IntPtr.Zero;
}
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jlongArray NewLongArray(JNIEnv* pEnv, jsize len)
{
try
{
return pEnv->MakeLocalRef(new long[len]);
}
catch(Exception x)
{
SetPendingException(pEnv, x);
return IntPtr.Zero;
}
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jfloatArray NewFloatArray(JNIEnv* pEnv, jsize len)
{
try
{
return pEnv->MakeLocalRef(new float[len]);
}
catch(Exception x)
{
SetPendingException(pEnv, x);
return IntPtr.Zero;
}
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jdoubleArray NewDoubleArray(JNIEnv* pEnv, jsize len)
{
try
{
return pEnv->MakeLocalRef(new double[len]);
}
catch(Exception x)
{
SetPendingException(pEnv, x);
return IntPtr.Zero;
}
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jboolean* GetBooleanArrayElements(JNIEnv* pEnv, jbooleanArray array, jboolean* isCopy)
{
bool[] b = (bool[])pEnv->UnwrapRef(array);
jboolean* p = (jboolean*)(void*)JniMem.Alloc(b.Length * 1);
for(int i = 0; i < b.Length; i++)
{
p[i] = b[i] ? JNI_TRUE : JNI_FALSE;
}
if(isCopy != null)
{
*isCopy = JNI_TRUE;
}
return p;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jbyte* GetByteArrayElements(JNIEnv* pEnv, jbyteArray array, jboolean* isCopy)
{
2005-02-02 18:11:26 +03:00
byte[] b = (byte[])pEnv->UnwrapRef(array);
2004-09-09 15:17:55 +04:00
jbyte* p = (jbyte*)(void*)JniMem.Alloc(b.Length * 1);
for(int i = 0; i < b.Length; i++)
{
p[i] = (jbyte)b[i];
}
if(isCopy != null)
{
*isCopy = JNI_TRUE;
}
return p;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jchar* GetCharArrayElements(JNIEnv* pEnv, jcharArray array, jboolean* isCopy)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
char[] b = (char[])pEnv->UnwrapRef(array);
IntPtr buf = JniMem.Alloc(b.Length * 2);
Marshal.Copy(b, 0, buf, b.Length);
if(isCopy != null)
{
*isCopy = JNI_TRUE;
}
return (jchar*)(void*)buf;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jshort* GetShortArrayElements(JNIEnv* pEnv, jshortArray array, jboolean* isCopy)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
short[] b = (short[])pEnv->UnwrapRef(array);
IntPtr buf = JniMem.Alloc(b.Length * 2);
Marshal.Copy(b, 0, buf, b.Length);
if(isCopy != null)
{
*isCopy = JNI_TRUE;
}
return (jshort*)(void*)buf;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jint* GetIntArrayElements(JNIEnv* pEnv, jintArray array, jboolean* isCopy)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
int[] b = (int[])pEnv->UnwrapRef(array);
IntPtr buf = JniMem.Alloc(b.Length * 4);
Marshal.Copy(b, 0, buf, b.Length);
if(isCopy != null)
{
*isCopy = JNI_TRUE;
}
return (jint*)(void*)buf;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jlong* GetLongArrayElements(JNIEnv* pEnv, jlongArray array, jboolean* isCopy)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
long[] b = (long[])pEnv->UnwrapRef(array);
IntPtr buf = JniMem.Alloc(b.Length * 8);
Marshal.Copy(b, 0, buf, b.Length);
if(isCopy != null)
{
*isCopy = JNI_TRUE;
}
return (jlong*)(void*)buf;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jfloat* GetFloatArrayElements(JNIEnv* pEnv, jfloatArray array, jboolean* isCopy)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
float[] b = (float[])pEnv->UnwrapRef(array);
IntPtr buf = JniMem.Alloc(b.Length * 4);
Marshal.Copy(b, 0, buf, b.Length);
if(isCopy != null)
{
*isCopy = JNI_TRUE;
}
return (jfloat*)(void*)buf;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static jdouble* GetDoubleArrayElements(JNIEnv* pEnv, jdoubleArray array, jboolean* isCopy)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
double[] b = (double[])pEnv->UnwrapRef(array);
IntPtr buf = JniMem.Alloc(b.Length * 8);
Marshal.Copy(b, 0, buf, b.Length);
if(isCopy != null)
{
*isCopy = JNI_TRUE;
}
return (jdouble*)(void*)buf;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void ReleaseBooleanArrayElements(JNIEnv* pEnv, jbooleanArray array, jboolean* elems, jint mode)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(mode == 0 || mode == JNI_COMMIT)
{
bool[] b = (bool[])pEnv->UnwrapRef(array);
for(int i = 0; i < b.Length; i++)
{
b[i] = elems[i] != JNI_FALSE;
}
}
if(mode == 0 || mode == JNI_ABORT)
{
JniMem.Free((IntPtr)(void*)elems);
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void ReleaseByteArrayElements(JNIEnv* pEnv, jbyteArray array, jbyte* elems, jint mode)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(mode == 0 || mode == JNI_COMMIT)
{
2005-02-02 18:11:26 +03:00
byte[] b = (byte[])pEnv->UnwrapRef(array);
2004-09-09 15:17:55 +04:00
for(int i = 0; i < b.Length; i++)
{
2005-02-02 18:11:26 +03:00
b[i] = (byte)elems[i];
2004-09-09 15:17:55 +04:00
}
}
if(mode == 0 || mode == JNI_ABORT)
{
JniMem.Free((IntPtr)(void*)elems);
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void ReleaseCharArrayElements(JNIEnv* pEnv, jcharArray array, jchar* elems, jint mode)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(mode == 0 || mode == JNI_COMMIT)
{
char[] b = (char[])pEnv->UnwrapRef(array);
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
}
if(mode == 0 || mode == JNI_ABORT)
{
JniMem.Free((IntPtr)(void*)elems);
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void ReleaseShortArrayElements(JNIEnv* pEnv, jshortArray array, jshort* elems, jint mode)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(mode == 0 || mode == JNI_COMMIT)
{
short[] b = (short[])pEnv->UnwrapRef(array);
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
}
if(mode == 0 || mode == JNI_ABORT)
{
JniMem.Free((IntPtr)(void*)elems);
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void ReleaseIntArrayElements(JNIEnv* pEnv, jintArray array, jint* elems, jint mode)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(mode == 0 || mode == JNI_COMMIT)
{
int[] b = (int[])pEnv->UnwrapRef(array);
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
}
if(mode == 0 || mode == JNI_ABORT)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
JniMem.Free((IntPtr)(void*)elems);
2004-08-30 19:56:23 +04:00
}
}
2004-09-09 15:17:55 +04:00
internal static void ReleaseLongArrayElements(JNIEnv* pEnv, jlongArray array, jlong* elems, jint mode)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(mode == 0 || mode == JNI_COMMIT)
{
long[] b = (long[])pEnv->UnwrapRef(array);
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
}
if(mode == 0 || mode == JNI_ABORT)
{
JniMem.Free((IntPtr)(void*)elems);
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void ReleaseFloatArrayElements(JNIEnv* pEnv, jfloatArray array, jfloat* elems, jint mode)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(mode == 0 || mode == JNI_COMMIT)
{
float[] b = (float[])pEnv->UnwrapRef(array);
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
}
if(mode == 0 || mode == JNI_ABORT)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
JniMem.Free((IntPtr)(void*)elems);
2004-08-30 19:56:23 +04:00
}
}
2004-09-09 15:17:55 +04:00
internal static void ReleaseDoubleArrayElements(JNIEnv* pEnv, jdoubleArray array, jdouble* elems, jint mode)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
if(mode == 0 || mode == JNI_COMMIT)
{
double[] b = (double[])pEnv->UnwrapRef(array);
Marshal.Copy((IntPtr)(void*)elems, b, 0, b.Length);
}
if(mode == 0 || mode == JNI_ABORT)
{
JniMem.Free((IntPtr)(void*)elems);
}
2004-08-17 13:05:21 +04:00
}
2003-01-07 14:40:11 +03:00
2004-09-09 15:17:55 +04:00
internal static void GetBooleanArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
bool[] b = (bool[])pEnv->UnwrapRef(array);
sbyte* p = (sbyte*)(void*)buf;
for(int i = 0; i < len; i++)
{
*p++ = b[start + i] ? JNI_TRUE : JNI_FALSE;
}
}
catch(IndexOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void GetByteArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
2005-02-02 18:11:26 +03:00
byte[] b = (byte[])pEnv->UnwrapRef(array);
byte* p = (byte*)(void*)buf;
2004-09-09 15:17:55 +04:00
for(int i = 0; i < len; i++)
{
*p++ = b[start + i];
}
}
catch(IndexOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2003-01-17 17:34:33 +03:00
2004-09-09 15:17:55 +04:00
internal static void GetCharArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2003-01-07 14:40:11 +03:00
{
2004-09-09 15:17:55 +04:00
try
{
char[] b = (char[])pEnv->UnwrapRef(array);
Marshal.Copy(b, start, buf, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void GetShortArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
short[] b = (short[])pEnv->UnwrapRef(array);
Marshal.Copy(b, start, buf, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2003-01-07 14:40:11 +03:00
}
2003-01-17 17:34:33 +03:00
2004-09-09 15:17:55 +04:00
internal static void GetIntArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
int[] b = (int[])pEnv->UnwrapRef(array);
Marshal.Copy(b, start, buf, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void GetLongArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
long[] b = (long[])pEnv->UnwrapRef(array);
Marshal.Copy(b, start, buf, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2003-01-17 17:34:33 +03:00
2004-09-09 15:17:55 +04:00
internal static void GetFloatArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
float[] b = (float[])pEnv->UnwrapRef(array);
Marshal.Copy(b, start, buf, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void GetDoubleArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
double[] b = (double[])pEnv->UnwrapRef(array);
Marshal.Copy(b, start, buf, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2003-01-07 14:40:11 +03:00
2004-09-09 15:17:55 +04:00
internal static void SetBooleanArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
bool[] b = (bool[])pEnv->UnwrapRef(array);
sbyte* p = (sbyte*)(void*)buf;
for(int i = 0; i < len; i++)
{
b[start + i] = *p++ != JNI_FALSE;
}
}
catch(IndexOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void SetByteArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
2005-02-02 18:11:26 +03:00
byte[] b = (byte[])pEnv->UnwrapRef(array);
byte* p = (byte*)(void*)buf;
2004-09-09 15:17:55 +04:00
for(int i = 0; i < len; i++)
{
b[start + i] = *p++;
}
}
catch(IndexOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2003-01-07 14:40:11 +03:00
2004-09-09 15:17:55 +04:00
internal static void SetCharArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
char[] b = (char[])pEnv->UnwrapRef(array);
Marshal.Copy(buf, b, start, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void SetShortArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
short[] b = (short[])pEnv->UnwrapRef(array);
Marshal.Copy(buf, b, start, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2003-01-07 14:40:11 +03:00
2004-09-09 15:17:55 +04:00
internal static void SetIntArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
int[] b = (int[])pEnv->UnwrapRef(array);
Marshal.Copy(buf, b, start, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetLongArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
long[] b = (long[])pEnv->UnwrapRef(array);
Marshal.Copy(buf, b, start, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetFloatArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
float[] b = (float[])pEnv->UnwrapRef(array);
Marshal.Copy(buf, b, start, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void SetDoubleArrayRegion(JNIEnv* pEnv, IntPtr array, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
double[] b = (double[])pEnv->UnwrapRef(array);
Marshal.Copy(buf, b, start, len);
}
catch(ArgumentOutOfRangeException)
{
SetPendingException(pEnv, JavaException.ArrayIndexOutOfBoundsException());
}
2004-08-17 13:05:21 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
[StructLayout(LayoutKind.Sequential)]
unsafe internal struct JNINativeMethod
{
public byte* name;
public byte* signature;
public void* fnPtr;
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static int RegisterNatives(JNIEnv* pEnv, IntPtr clazz, JNINativeMethod* methods, int nMethods)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
2004-08-30 19:56:23 +04:00
{
2006-03-27 17:59:59 +04:00
TypeWrapper wrapper = TypeWrapper.FromClass(pEnv->UnwrapRef(clazz));
2004-09-09 15:17:55 +04:00
wrapper.Finish();
for(int i = 0; i < nMethods; i++)
2004-08-30 19:56:23 +04:00
{
2005-02-23 15:56:15 +03:00
string methodName = StringFromUTF8(methods[i].name);
string methodSig = StringFromUTF8(methods[i].signature);
Tracer.Info(Tracer.Jni, "Registering native method: {0}.{1}{2}, fnPtr = 0x{3:X}", wrapper.Name, methodName, methodSig, ((IntPtr)methods[i].fnPtr).ToInt64());
2005-02-16 14:20:43 +03:00
FieldInfo fi = null;
// don't allow dotted names!
2005-02-23 15:56:15 +03:00
if(methodSig.IndexOf('.') < 0)
2005-02-16 14:20:43 +03:00
{
// TODO this won't work when we're putting the JNI methods in jniproxy.dll
2005-02-23 15:56:15 +03:00
fi = wrapper.TypeAsTBD.GetField(JNI.METHOD_PTR_FIELD_PREFIX + methodName + methodSig, BindingFlags.Static | BindingFlags.NonPublic);
2005-02-16 14:20:43 +03:00
}
2004-09-09 15:17:55 +04:00
if(fi == null)
{
2005-02-23 15:56:15 +03:00
Tracer.Error(Tracer.Jni, "Failed to register native method: {0}.{1}{2}", wrapper.Name, methodName, methodSig);
SetPendingException(pEnv, JavaException.NoSuchMethodError(methodName));
2004-09-09 15:17:55 +04:00
return JNI_ERR;
}
fi.SetValue(null, (IntPtr)methods[i].fnPtr);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
return JNI_OK;
}
2004-12-21 17:59:29 +03:00
catch(RetargetableJavaException x)
{
SetPendingException(pEnv, x.ToJava());
return JNI_ERR;
}
2004-09-09 15:17:55 +04:00
catch(Exception x)
{
SetPendingException(pEnv, x);
return JNI_ERR;
2004-08-30 19:56:23 +04:00
}
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
internal static int UnregisterNatives(JNIEnv* pEnv, IntPtr clazz)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
2004-08-30 19:56:23 +04:00
{
2006-03-27 17:59:59 +04:00
TypeWrapper wrapper = TypeWrapper.FromClass(pEnv->UnwrapRef(clazz));
2004-09-09 15:17:55 +04:00
wrapper.Finish();
2004-11-24 13:57:11 +03:00
// TODO this won't work when we're putting the JNI methods in jniproxy.dll
2004-09-09 15:17:55 +04:00
foreach(FieldInfo fi in wrapper.TypeAsTBD.GetFields(BindingFlags.Static | BindingFlags.NonPublic))
2004-08-30 19:56:23 +04:00
{
2005-02-23 15:56:15 +03:00
string name = fi.Name;
if(name.StartsWith(JNI.METHOD_PTR_FIELD_PREFIX))
2004-09-09 15:17:55 +04:00
{
2005-02-23 15:56:15 +03:00
Tracer.Info(Tracer.Jni, "Unregistering native method: {0}.{1}", wrapper.Name, name.Substring(JNI.METHOD_PTR_FIELD_PREFIX.Length));
2004-09-09 15:17:55 +04:00
fi.SetValue(null, IntPtr.Zero);
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
return JNI_OK;
}
2004-12-21 17:59:29 +03:00
catch(RetargetableJavaException x)
{
SetPendingException(pEnv, x.ToJava());
return JNI_ERR;
}
2004-09-09 15:17:55 +04:00
catch(Exception x)
{
SetPendingException(pEnv, x);
return JNI_ERR;
2004-08-30 19:56:23 +04:00
}
2004-08-17 13:05:21 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static int MonitorEnter(JNIEnv* pEnv, IntPtr obj)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
2005-01-03 11:26:21 +03:00
System.Threading.Monitor.Enter(pEnv->UnwrapRef(obj));
2004-09-09 15:17:55 +04:00
return JNI_OK;
}
2004-09-27 14:17:34 +04:00
catch(Exception x)
2004-09-09 15:17:55 +04:00
{
2004-09-27 14:17:34 +04:00
SetPendingException(pEnv, x);
2004-09-09 15:17:55 +04:00
return JNI_ERR;
}
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
internal static int MonitorExit(JNIEnv* pEnv, IntPtr obj)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
try
{
System.Threading.Monitor.Exit(pEnv->UnwrapRef(obj));
return JNI_OK;
}
2004-09-27 14:17:34 +04:00
catch(Exception x)
2004-09-09 15:17:55 +04:00
{
2004-09-27 14:17:34 +04:00
SetPendingException(pEnv, x);
2004-09-09 15:17:55 +04:00
return JNI_ERR;
}
2004-08-17 13:05:21 +04:00
}
2004-04-23 15:34:32 +04:00
2004-09-09 15:17:55 +04:00
internal static int GetJavaVM(JNIEnv* pEnv, JavaVM **ppJavaVM)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
*ppJavaVM = JavaVM.pJavaVM;
2004-08-30 19:56:23 +04:00
return JNI_OK;
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void GetStringRegion(JNIEnv* pEnv, IntPtr str, int start, int len, IntPtr buf)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
string s = (string)pEnv->UnwrapRef(str);
if(s != null)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(start < 0 || start > s.Length || s.Length - start < len)
{
2004-11-29 12:48:01 +03:00
SetPendingException(pEnv, JavaException.StringIndexOutOfBoundsException());
2004-09-09 15:17:55 +04:00
return;
}
else
{
char* p = (char*)(void*)buf;
// TODO isn't there a managed memcpy?
for(int i = 0; i < len; i++)
{
*p++ = s[start + i];
}
return;
}
2004-08-30 19:56:23 +04:00
}
else
{
2004-09-09 15:17:55 +04:00
SetPendingException(pEnv, JavaException.NullPointerException());
2004-08-30 19:56:23 +04:00
}
}
2004-09-09 15:17:55 +04:00
internal static void GetStringUTFRegion(JNIEnv* pEnv, IntPtr str, int start, int len, IntPtr buf)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
string s = (string)pEnv->UnwrapRef(str);
if(s != null)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
if(start < 0 || start > s.Length || s.Length - start < len)
2004-08-30 19:56:23 +04:00
{
2004-11-29 12:48:01 +03:00
SetPendingException(pEnv, JavaException.StringIndexOutOfBoundsException());
2004-09-09 15:17:55 +04:00
return;
}
else
{
byte* p = (byte*)(void*)buf;
for(int i = 0; i < len; i++)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
char ch = s[start + i];
if((ch != 0) && (ch <= 0x7F))
{
*p++ = (byte)ch;
}
else if(ch <= 0x7FF)
{
*p++ = (byte)((ch >> 6) | 0xC0);
*p++ = (byte)((ch & 0x3F) | 0x80);
}
else
{
*p++ = (byte)((ch >> 12) | 0xE0);
*p++ = (byte)(((ch >> 6) & 0x3F) | 0x80);
*p++ = (byte)((ch & 0x3F) | 0x80);
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
return;
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
}
else
{
SetPendingException(pEnv, JavaException.NullPointerException());
2004-08-30 19:56:23 +04:00
}
}
2004-08-17 13:05:21 +04:00
2004-09-09 15:17:55 +04:00
private static int GetPrimitiveArrayElementSize(Array ar)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
Type type = ar.GetType().GetElementType();
2005-02-02 18:11:26 +03:00
if(type == PrimitiveTypeWrapper.BYTE.TypeAsArrayType || type == PrimitiveTypeWrapper.BOOLEAN.TypeAsArrayType)
2004-09-09 15:17:55 +04:00
{
return 1;
}
2005-02-02 18:11:26 +03:00
else if(type == PrimitiveTypeWrapper.SHORT.TypeAsArrayType || type == PrimitiveTypeWrapper.CHAR.TypeAsArrayType)
2004-09-09 15:17:55 +04:00
{
return 2;
}
2005-02-02 18:11:26 +03:00
else if(type == PrimitiveTypeWrapper.INT.TypeAsArrayType || type == PrimitiveTypeWrapper.FLOAT.TypeAsArrayType)
2004-09-09 15:17:55 +04:00
{
return 4;
}
2005-02-02 18:11:26 +03:00
else if(type == PrimitiveTypeWrapper.LONG.TypeAsArrayType || type == PrimitiveTypeWrapper.DOUBLE.TypeAsArrayType)
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
return 8;
2004-08-17 13:05:21 +04:00
}
2004-09-09 15:17:55 +04:00
else
2004-08-17 13:05:21 +04:00
{
2004-09-09 15:17:55 +04:00
JVM.CriticalFailure("invalid array type", null);
return 0;
2004-08-17 13:05:21 +04:00
}
}
2005-09-01 11:34:53 +04:00
internal static void* GetPrimitiveArrayCritical(JNIEnv* pEnv, jarray array, jboolean* isCopy)
2004-08-17 13:05:21 +04:00
{
2004-08-30 19:56:23 +04:00
Array ar = (Array)pEnv->UnwrapRef(array);
2005-09-01 11:34:53 +04:00
if(pEnv->criticalArrayHandle1.Target == null)
{
pEnv->criticalArrayHandle1.Target = ar;
if(isCopy != null)
{
*isCopy = JNI_FALSE;
}
return (void*)pEnv->criticalArrayHandle1.AddrOfPinnedObject();
}
if(pEnv->criticalArrayHandle2.Target == null)
{
pEnv->criticalArrayHandle2.Target = ar;
if(isCopy != null)
{
*isCopy = JNI_FALSE;
}
return (void*)pEnv->criticalArrayHandle2.AddrOfPinnedObject();
}
2005-02-02 18:11:26 +03:00
// TODO not 64-bit safe (len can overflow)
2004-08-30 19:56:23 +04:00
int len = ar.Length * GetPrimitiveArrayElementSize(ar);
GCHandle h = GCHandle.Alloc(ar, GCHandleType.Pinned);
try
{
2004-09-09 15:17:55 +04:00
IntPtr hglobal = JniMem.Alloc(len);
byte* pdst = (byte*)(void*)hglobal;
byte* psrc = (byte*)(void*)h.AddrOfPinnedObject();
2004-08-30 19:56:23 +04:00
// TODO isn't there a managed memcpy?
for(int i = 0; i < len; i++)
{
*pdst++ = *psrc++;
}
2005-09-01 11:34:53 +04:00
if(isCopy != null)
2004-09-09 15:17:55 +04:00
{
2005-09-01 11:34:53 +04:00
*isCopy = JNI_TRUE;
2004-09-09 15:17:55 +04:00
}
2005-09-01 11:34:53 +04:00
return (void*)hglobal;
2004-08-30 19:56:23 +04:00
}
finally
{
h.Free();
2004-09-09 15:17:55 +04:00
}
2004-08-17 13:05:21 +04:00
}
2005-09-01 11:34:53 +04:00
internal static void ReleasePrimitiveArrayCritical(JNIEnv* pEnv, jarray array, void* carray, jint mode)
2004-08-30 19:56:23 +04:00
{
2005-09-01 11:34:53 +04:00
Array ar = (Array)pEnv->UnwrapRef(array);
if(pEnv->criticalArrayHandle1.Target == ar
&& (void*)pEnv->criticalArrayHandle1.AddrOfPinnedObject() == carray)
{
if(mode == 0 || mode == JNI_ABORT)
{
pEnv->criticalArrayHandle1.Target = null;
}
return;
}
if(pEnv->criticalArrayHandle2.Target == ar
&& (void*)pEnv->criticalArrayHandle2.AddrOfPinnedObject() == carray)
{
if(mode == 0 || mode == JNI_ABORT)
{
pEnv->criticalArrayHandle2.Target = null;
}
return;
}
2004-09-09 15:17:55 +04:00
if(mode == 0 || mode == JNI_COMMIT)
{
2005-02-02 18:11:26 +03:00
// TODO not 64-bit safe (len can overflow)
2004-09-09 15:17:55 +04:00
int len = ar.Length * GetPrimitiveArrayElementSize(ar);
GCHandle h = GCHandle.Alloc(ar, GCHandleType.Pinned);
try
{
byte* pdst = (byte*)(void*)h.AddrOfPinnedObject();
byte* psrc = (byte*)(void*)carray;
// TODO isn't there a managed memcpy?
for(int i = 0; i < len; i++)
{
*pdst++ = *psrc++;
}
}
finally
{
h.Free();
}
}
if(mode == 0 || mode == JNI_ABORT)
2004-08-30 19:56:23 +04:00
{
2005-09-01 11:34:53 +04:00
JniMem.Free((IntPtr)carray);
2004-08-30 19:56:23 +04:00
}
}
2005-09-01 11:34:53 +04:00
internal static jchar* GetStringCritical(JNIEnv* pEnv, jstring str, jboolean* isCopy)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
string s = (string)pEnv->UnwrapRef(str);
if(s != null)
2004-09-05 13:37:58 +04:00
{
2005-09-01 11:34:53 +04:00
if(isCopy != null)
2004-09-05 13:37:58 +04:00
{
2005-09-01 11:34:53 +04:00
*isCopy = JNI_TRUE;
2004-09-05 13:37:58 +04:00
}
2005-09-01 11:34:53 +04:00
return (jchar*)(void*)Marshal.StringToHGlobalUni(s);
2004-09-05 13:37:58 +04:00
}
2004-09-09 15:17:55 +04:00
SetPendingException(pEnv, JavaException.NullPointerException());
2005-09-01 11:34:53 +04:00
return null;
2004-09-05 13:37:58 +04:00
}
2005-09-01 11:34:53 +04:00
internal static void ReleaseStringCritical(JNIEnv* pEnv, jstring str, jchar* cstring)
2004-09-05 13:37:58 +04:00
{
2005-09-01 11:34:53 +04:00
Marshal.FreeHGlobal((IntPtr)(void*)cstring);
2004-09-05 13:37:58 +04:00
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static jweak NewWeakGlobalRef(JNIEnv* pEnv, jobject obj)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
object o = pEnv->UnwrapRef(obj);
if(o == null)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
return IntPtr.Zero;
}
lock(GlobalRefs.weakRefLock)
{
for(int i = 0; i < GlobalRefs.weakRefs.Length; i++)
{
2005-05-17 17:18:16 +04:00
if(!GlobalRefs.weakRefs[i].IsAllocated)
2004-09-09 15:17:55 +04:00
{
GlobalRefs.weakRefs[i] = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
return (IntPtr)(- (i | (1 << 30)));
}
}
int len = GlobalRefs.weakRefs.Length;
GCHandle[] tmp = new GCHandle[len * 2];
Array.Copy(GlobalRefs.weakRefs, 0, tmp, 0, len);
tmp[len] = GCHandle.Alloc(o, GCHandleType.WeakTrackResurrection);
GlobalRefs.weakRefs = tmp;
return (IntPtr)(- (len | (1 << 30)));
2004-09-05 13:37:58 +04:00
}
}
2004-08-30 19:56:23 +04:00
2004-09-09 15:17:55 +04:00
internal static void DeleteWeakGlobalRef(JNIEnv* pEnv, jweak obj)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
int i = obj.ToInt32();
if(i < 0)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
i = -i;
i -= (1 << 30);
2004-09-05 13:37:58 +04:00
lock(GlobalRefs.weakRefLock)
{
2004-09-09 15:17:55 +04:00
GlobalRefs.weakRefs[i].Free();
2004-09-05 13:37:58 +04:00
}
}
2004-09-09 15:17:55 +04:00
if(i > 0)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
Debug.Assert(false, "local ref passed to DeleteWeakGlobalRef");
2004-09-05 13:37:58 +04:00
}
2004-08-30 19:56:23 +04:00
}
2005-02-02 18:11:26 +03:00
internal static jboolean ExceptionCheck(JNIEnv* pEnv)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
return pEnv->UnwrapRef(pEnv->pendingException) != null ? JNI_TRUE : JNI_FALSE;
2004-09-05 13:37:58 +04:00
}
2004-08-30 19:56:23 +04:00
2004-11-23 20:46:39 +03:00
internal static jobject NewDirectByteBuffer(JNIEnv* pEnv, IntPtr address, jlong capacity)
2004-08-30 19:56:23 +04:00
{
2004-11-23 20:46:39 +03:00
try
{
if(capacity < 0 || capacity > int.MaxValue)
{
SetPendingException(pEnv, JavaException.IllegalArgumentException("capacity"));
return IntPtr.Zero;
}
2004-11-29 16:58:21 +03:00
return pEnv->MakeLocalRef(JVM.Library.newDirectByteBuffer(address, (int)capacity));
2004-11-23 20:46:39 +03:00
}
catch(Exception x)
{
2006-08-17 11:33:38 +04:00
SetPendingException(pEnv, JVM.Library.mapException(x));
2004-11-23 20:46:39 +03:00
return IntPtr.Zero;
}
}
internal static IntPtr GetDirectBufferAddress(JNIEnv* pEnv, jobject buf)
{
try
{
2004-11-29 16:58:21 +03:00
return JVM.Library.getDirectBufferAddress(pEnv->UnwrapRef(buf));
2004-11-23 20:46:39 +03:00
}
catch(Exception x)
{
2006-08-17 11:33:38 +04:00
SetPendingException(pEnv, JVM.Library.mapException(x));
2004-11-23 20:46:39 +03:00
return IntPtr.Zero;
}
}
internal static jlong GetDirectBufferCapacity(JNIEnv* pEnv, jobject buf)
{
try
{
2004-11-29 16:58:21 +03:00
return (jlong)(long)JVM.Library.getDirectBufferCapacity(pEnv->UnwrapRef(buf));
2004-11-23 20:46:39 +03:00
}
catch(Exception x)
{
2006-08-17 11:33:38 +04:00
SetPendingException(pEnv, JVM.Library.mapException(x));
2004-11-23 20:46:39 +03:00
return 0;
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal IntPtr MakeLocalRef(object obj)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
if(obj == null)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
return IntPtr.Zero;
2004-09-05 13:37:58 +04:00
}
2004-09-09 15:17:55 +04:00
object[][] localRefs = GetLocalRefs();
object[] active = localRefs[localRefSlot];
for(int i = 0; i < active.Length; i++)
{
if(active[i] == null)
{
active[i] = obj;
return (IntPtr)((localRefSlot << LOCAL_REF_SHIFT) + i);
}
}
if(active.Length < LOCAL_REF_BUCKET_SIZE)
{
int i = active.Length;
object[] tmp = new object[i * 2];
Array.Copy(active, 0, tmp, 0, i);
active = localRefs[localRefSlot] = tmp;
active[i] = obj;
return (IntPtr)((localRefSlot << LOCAL_REF_SHIFT) + i);
}
// if we get here, we're in a native method that most likely is leaking locals refs,
// so we're going to allocate a new bucket and increment localRefSlot, this means that
// any slots that become available in the previous bucket are not going to be reused,
// but since we're assuming that the method is leaking anyway, that isn't a problem
// (it's never a correctness issue, just a resource consumption issue)
localRefSlot++;
if(localRefSlot == localRefs.Length)
{
object[][] tmp = new object[localRefSlot * 2][];
Array.Copy(localRefs, 0, tmp, 0, localRefSlot);
this.localRefs.Target = localRefs = tmp;
}
if(localRefs[localRefSlot] == null)
{
localRefs[localRefSlot] = new object[LOCAL_REF_BUCKET_SIZE];
}
localRefs[localRefSlot][0] = obj;
return (IntPtr)(localRefSlot << LOCAL_REF_SHIFT);
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
internal object UnwrapRef(IntPtr o)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
int i = o.ToInt32();
if(i > 0)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
object[][] localRefs = GetLocalRefs();
return localRefs[i >> LOCAL_REF_SHIFT][i & LOCAL_REF_MASK];
}
if(i < 0)
{
i = -i;
if((i & (1 << 30)) != 0)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
lock(GlobalRefs.weakRefLock)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return GlobalRefs.weakRefs[i - (1 << 30)].Target;
2004-08-30 19:56:23 +04:00
}
}
2004-09-09 15:17:55 +04:00
else
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
lock(GlobalRefs.globalRefs)
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
return GlobalRefs.globalRefs[i - 1];
2004-08-30 19:56:23 +04:00
}
}
}
2004-09-09 15:17:55 +04:00
return null;
2004-08-30 19:56:23 +04:00
}
}
2004-09-09 15:17:55 +04:00
class JniMem
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
internal static IntPtr Alloc(int cb)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
return Marshal.AllocHGlobal(cb);
2004-09-05 13:37:58 +04:00
}
2004-09-09 15:17:55 +04:00
internal static void Free(IntPtr p)
2004-09-05 13:37:58 +04:00
{
2004-09-09 15:17:55 +04:00
Marshal.FreeHGlobal(p);
2004-09-05 13:37:58 +04:00
}
2004-08-30 19:56:23 +04:00
}
2004-09-09 15:17:55 +04:00
unsafe class TlsHack
2004-08-30 19:56:23 +04:00
{
2004-09-09 15:17:55 +04:00
[ThreadStatic]
internal static JNIEnv* pJNIEnv;
2004-08-30 19:56:23 +04:00
}
2003-01-07 14:40:11 +03:00
}
2005-12-07 12:06:32 +03:00
#endif