2003-01-07 14:40:11 +03:00
|
|
|
/*
|
2005-01-05 15:56:37 +03:00
|
|
|
Copyright (C) 2002, 2003, 2004, 2005 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
|
|
|
|
|
|
|
|
*/
|
|
|
|
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 sbyte* optionString;
|
|
|
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
internal static bool jvmCreated;
|
2004-11-23 20:46:39 +03:00
|
|
|
internal const string METHOD_PTR_FIELD_PREFIX = "__<jniptr/";
|
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
|
|
|
|
if(pInitArgs->version != JNIEnv.JNI_VERSION_1_2)
|
|
|
|
{
|
|
|
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
string option = new String(pInitArgs->options[i].optionString);
|
|
|
|
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
|
|
|
|
2004-09-15 17:35:44 +04:00
|
|
|
Startup.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;
|
|
|
|
}
|
|
|
|
*nVMs = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*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;
|
|
|
|
}
|
|
|
|
|
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);
|
|
|
|
// MONOBUG Mono 1.0 doesn't implement MethodBase.GetMethodFromHandle
|
|
|
|
if(mb == null)
|
2004-08-30 19:56:23 +04:00
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
mb = new StackFrame(1).GetMethod();
|
2004-08-30 19:56:23 +04:00
|
|
|
}
|
2004-09-09 15:17:55 +04:00
|
|
|
ClassLoaderWrapper loader = ClassLoaderWrapper.GetWrapperFromType(mb.DeclaringType).GetClassLoader();
|
|
|
|
StringBuilder mangledSig = new StringBuilder();
|
|
|
|
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 '[':
|
|
|
|
mangledSig.Append("_3");
|
|
|
|
sp += IntPtr.Size;
|
|
|
|
while(sig[++i] == '[')
|
|
|
|
{
|
|
|
|
mangledSig.Append("_3");
|
|
|
|
}
|
|
|
|
mangledSig.Append(sig[i]);
|
|
|
|
if(sig[i] == 'L')
|
|
|
|
{
|
|
|
|
while(sig[++i] != ';')
|
|
|
|
{
|
|
|
|
if(sig[i] == '/')
|
|
|
|
{
|
|
|
|
mangledSig.Append("_");
|
|
|
|
}
|
|
|
|
else if(sig[i] == '_')
|
|
|
|
{
|
|
|
|
mangledSig.Append("_1");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mangledSig.Append(sig[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mangledSig.Append("_2");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
sp += IntPtr.Size;
|
|
|
|
mangledSig.Append("L");
|
|
|
|
while(sig[++i] != ';')
|
|
|
|
{
|
|
|
|
if(sig[i] == '/')
|
|
|
|
{
|
|
|
|
mangledSig.Append("_");
|
|
|
|
}
|
|
|
|
else if(sig[i] == '_')
|
|
|
|
{
|
|
|
|
mangledSig.Append("_1");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mangledSig.Append(sig[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mangledSig.Append("_2");
|
|
|
|
break;
|
|
|
|
case 'J':
|
|
|
|
case 'D':
|
|
|
|
mangledSig.Append(sig[i]);
|
|
|
|
sp += 8;
|
|
|
|
break;
|
|
|
|
case 'F':
|
|
|
|
case 'I':
|
|
|
|
case 'C':
|
|
|
|
case 'Z':
|
|
|
|
case 'S':
|
|
|
|
case 'B':
|
|
|
|
mangledSig.Append(sig[i]);
|
|
|
|
sp += 4;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Debug.Assert(false);
|
|
|
|
break;
|
2004-08-30 19:56:23 +04:00
|
|
|
}
|
|
|
|
}
|
2004-09-09 15:17:55 +04:00
|
|
|
lock(JniHelper.JniLock)
|
|
|
|
{
|
|
|
|
string shortMethodName = String.Format("Java_{0}_{1}", clazz.Replace("_", "_1").Replace('/', '_'), name.Replace("_", "_1"));
|
|
|
|
string longMethodName = String.Format("Java_{0}_{1}__{2}", clazz.Replace("_", "_1").Replace('/', '_'), name.Replace("_", "_1"), mangledSig);
|
|
|
|
foreach(IntPtr p in loader.GetNativeLibraries())
|
|
|
|
{
|
|
|
|
IntPtr pfunc = JniHelper.ikvm_GetProcAddress(p, shortMethodName, sp + 2 * IntPtr.Size);
|
|
|
|
if(pfunc != IntPtr.Zero)
|
|
|
|
{
|
|
|
|
return pfunc;
|
|
|
|
}
|
|
|
|
pfunc = JniHelper.ikvm_GetProcAddress(p, longMethodName, sp + 2 * IntPtr.Size);
|
|
|
|
if(pfunc != IntPtr.Zero)
|
|
|
|
{
|
|
|
|
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
|
|
|
|
|
|
|
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 MethodBase FindCaller()
|
|
|
|
{
|
|
|
|
StackTrace st = new StackTrace();
|
|
|
|
for(int i = 0; i < st.FrameCount; i++)
|
|
|
|
{
|
|
|
|
StackFrame frame = st.GetFrame(i);
|
|
|
|
Type type = frame.GetMethod().DeclaringType;
|
2004-10-05 13:05:40 +04:00
|
|
|
if(type != null && type.Assembly != typeof(JniHelper).Assembly)
|
2004-09-09 15:17:55 +04:00
|
|
|
{
|
|
|
|
// TODO we need a more robust algorithm to find the "caller" (note that in addition to native methods,
|
|
|
|
// System.loadLibrary can also trigger executing native code)
|
|
|
|
ClassLoaderWrapper loader = ClassLoaderWrapper.GetWrapperFromType(type).GetClassLoader();
|
|
|
|
if(loader.GetJavaClassLoader() != null)
|
|
|
|
{
|
|
|
|
return frame.GetMethod();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2004-08-30 19:56:23 +04:00
|
|
|
|
2004-09-09 15:17:55 +04:00
|
|
|
private static ArrayList nativeLibraries = new ArrayList();
|
|
|
|
internal static readonly object JniLock = new object();
|
|
|
|
|
|
|
|
internal unsafe static int LoadLibrary(string filename)
|
2004-08-30 19:56:23 +04:00
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
MethodBase m = FindCaller();
|
|
|
|
ClassLoaderWrapper loader;
|
|
|
|
if(m != null)
|
2004-08-30 19:56:23 +04:00
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
loader = ClassLoaderWrapper.GetWrapperFromType(m.DeclaringType).GetClassLoader();
|
2004-08-30 19:56:23 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
loader = ClassLoaderWrapper.GetBootstrapClassLoader();
|
|
|
|
m = MethodBase.GetCurrentMethod();
|
|
|
|
}
|
|
|
|
lock(JniLock)
|
|
|
|
{
|
|
|
|
IntPtr p = ikvm_LoadLibrary(filename);
|
|
|
|
if(p == IntPtr.Zero)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(nativeLibraries.Contains(p))
|
|
|
|
{
|
|
|
|
throw JavaException.UnsatisfiedLinkError("Native library {0} already loaded in another classloader", filename);
|
|
|
|
}
|
|
|
|
IntPtr onload = ikvm_GetProcAddress(p, "JNI_OnLoad", IntPtr.Size * 2);
|
|
|
|
if(onload != IntPtr.Zero)
|
|
|
|
{
|
|
|
|
JNI.Frame f = new JNI.Frame();
|
2005-01-05 15:56:37 +03:00
|
|
|
ClassLoaderWrapper prevLoader = f.Enter(loader);
|
2004-09-09 15:17:55 +04:00
|
|
|
int version = ikvm_CallOnLoad(onload, JavaVM.pJavaVM, null);
|
2005-01-05 15:56:37 +03:00
|
|
|
f.Leave(prevLoader);
|
2004-09-09 15:17:55 +04:00
|
|
|
if(!JavaVM.IsSupportedJniVersion(version))
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
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);
|
2004-09-09 15:17:55 +04:00
|
|
|
|
|
|
|
internal static void* vtable;
|
|
|
|
|
|
|
|
static VtableBuilder()
|
|
|
|
{
|
|
|
|
// 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);
|
|
|
|
new pf_IntPtr_IntPtr_IntPtr(JNIEnv.ToReflectedMethod), //virtual jobject JNICALL ToReflectedMethod(jclass clazz, jmethodID methodID);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
new pf_IntPtr_IntPtr_IntPtr(JNIEnv.ToReflectedField), //virtual jobject JNICALL ToReflectedField(jclass clazz, jfieldID fieldID);
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetPrimitiveArrayCritical), //virtual void* JNICALL GetPrimitiveArrayCritical(jarray array, jboolean *isCopy);
|
|
|
|
new pf_void_IntPtr_IntPtr_int(JNIEnv.ReleasePrimitiveArrayCritical), //virtual void JNICALL ReleasePrimitiveArrayCritical(jarray array, void *carray, jint mode);
|
|
|
|
|
|
|
|
new pf_IntPtr_IntPtr_IntPtr(JNIEnv.GetStringCritical), //virtual const jchar* JNICALL GetStringCritical(jstring string, jboolean *isCopy);
|
|
|
|
new pf_void_IntPtr_IntPtr(JNIEnv.ReleaseStringCritical), //virtual void JNICALL ReleaseStringCritical(jstring string, const jchar *cstring);
|
|
|
|
|
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 sbyte* name;
|
|
|
|
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));
|
2004-08-30 19:56:23 +04:00
|
|
|
#if __MonoCS__
|
|
|
|
// MONOBUG mcs requires this bogus fixed construct (and Microsoft doesn't allow it)
|
|
|
|
fixed(void** p = &pJavaVM->firstVtableEntry) { pJavaVM->vtable = p; }
|
|
|
|
#else
|
2004-09-09 15:17:55 +04:00
|
|
|
pJavaVM->vtable = &pJavaVM->firstVtableEntry;
|
2004-08-30 19:56:23 +04:00
|
|
|
#endif
|
2004-09-09 15:17:55 +04:00
|
|
|
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
|
|
|
{
|
2004-11-29 16:58:21 +03:00
|
|
|
JVM.Library.jniWaitUntilLastThread();
|
2004-09-09 15:17:55 +04:00
|
|
|
return JNIEnv.JNI_ERR;
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
if(pAttachArgs->version != JNIEnv.JNI_VERSION_1_2)
|
|
|
|
{
|
|
|
|
*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.
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
System.Threading.Thread.CurrentThread.Name = new String(pAttachArgs->name);
|
|
|
|
}
|
|
|
|
// 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)
|
|
|
|
{
|
|
|
|
// TODO instead of using a thread data slot to communicate the thread group, we should probably use
|
|
|
|
// another mechanism, this is probably a security issue.
|
|
|
|
System.Threading.Thread.SetData(System.Threading.Thread.GetNamedDataSlot("ikvm-thread-group"), threadGroup);
|
|
|
|
}
|
2004-08-30 19:56:23 +04:00
|
|
|
}
|
2004-09-09 15:17:55 +04:00
|
|
|
System.Threading.Thread.CurrentThread.IsBackground = asDaemon;
|
|
|
|
*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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
return JNIEnv.JNI_EDETACHED;
|
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 bool IsSupportedJniVersion(jint version)
|
2004-08-30 19:56:23 +04:00
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
return version == JNIEnv.JNI_VERSION_1_1 || version == JNIEnv.JNI_VERSION_1_2 || version == JNIEnv.JNI_VERSION_1_4;
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
if(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
|
|
|
|
{
|
|
|
|
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;
|
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()
|
|
|
|
{
|
|
|
|
pJNIEnv->localRefs.Free();
|
2005-01-05 15:56:37 +03:00
|
|
|
pJNIEnv->classLoader.Free();
|
2004-09-09 15:17:55 +04:00
|
|
|
JniMem.Free((IntPtr)(void*)pJNIEnv);
|
|
|
|
}
|
|
|
|
}
|
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));
|
2004-09-15 17:35:44 +04:00
|
|
|
//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);
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
// the cleanup helper will eventually free the JNIEnv
|
|
|
|
System.Threading.Thread.SetData(cleanupHelperDataSlot, null);
|
|
|
|
TlsHack.pJNIEnv = null;
|
2004-08-30 19:56:23 +04:00
|
|
|
}
|
|
|
|
|
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.
|
2004-12-21 13:26:51 +03:00
|
|
|
return pEnv->MakeLocalRef(IKVM.NativeCode.java.lang.VMClassLoader.defineClassImpl(pEnv->UnwrapRef(loader), name != null ? new String((sbyte*)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);
|
|
|
|
if(mb != null)
|
|
|
|
{
|
|
|
|
ClassLoaderWrapper loader = ClassLoaderWrapper.GetWrapperFromType(mb.DeclaringType).GetClassLoader();
|
|
|
|
if(loader.GetJavaClassLoader() != null)
|
|
|
|
{
|
|
|
|
return loader;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// MONOBUG Mono 1.0 doesn't implement MethodBase.GetMethodFromHandle, so we do a stack walk
|
|
|
|
// to try and find the caller
|
|
|
|
StackTrace st = new StackTrace();
|
|
|
|
for(int i = 0; i < st.FrameCount; i++)
|
|
|
|
{
|
|
|
|
StackFrame frame = st.GetFrame(i);
|
|
|
|
Type type = frame.GetMethod().DeclaringType;
|
|
|
|
if(type != null && frame.GetMethod().MethodHandle.Value == pEnv->currentMethod.Value)
|
|
|
|
{
|
|
|
|
ClassLoaderWrapper loader = ClassLoaderWrapper.GetWrapperFromType(type).GetClassLoader();
|
|
|
|
if(loader.GetJavaClassLoader() != null)
|
|
|
|
{
|
|
|
|
return loader;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
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;
|
|
|
|
}
|
2004-09-09 15:17:55 +04:00
|
|
|
return ClassLoaderWrapper.GetSystemClassLoader();
|
2004-08-30 19:56:23 +04:00
|
|
|
}
|
2004-09-09 15:17:55 +04:00
|
|
|
|
|
|
|
internal static jclass FindClass(JNIEnv* pEnv, byte* name)
|
2004-08-30 19:56:23 +04:00
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
try
|
|
|
|
{
|
|
|
|
TypeWrapper wrapper = FindNativeMethodClassLoader(pEnv).LoadClassByDottedName(new String((sbyte*)name).Replace('/', '.'));
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
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
|
|
|
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
|
|
|
|
2004-09-09 15:17:55 +04:00
|
|
|
internal static jobject ToReflectedMethod(JNIEnv* pEnv, jclass clazz_ignored, jmethodID method)
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
TypeWrapper wrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(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)
|
|
|
|
{
|
|
|
|
TypeWrapper w1 = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(sub));
|
|
|
|
TypeWrapper w2 = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(super));
|
|
|
|
return w1.IsAssignableTo(w2) ? JNI_TRUE : JNI_FALSE;
|
2004-08-30 19:56:23 +04:00
|
|
|
}
|
|
|
|
|
2004-09-09 15:17:55 +04:00
|
|
|
internal static jobject ToReflectedField(JNIEnv* pEnv, jclass clazz_ignored, jfieldID field)
|
|
|
|
{
|
|
|
|
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);
|
2004-11-29 16:58:21 +03:00
|
|
|
pEnv->pendingException = x == null ? IntPtr.Zero : pEnv->MakeLocalRef(Util.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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
TypeWrapper wrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(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[] { new String((sbyte*)msg) }, false);
|
|
|
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
JVM.CriticalFailure(new String((sbyte*)msg), null);
|
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)
|
|
|
|
{
|
|
|
|
// we can't use capacity, because the array length must be a power of two
|
|
|
|
localRefs[pEnv->localRefSlot] = new object[LOCAL_REF_BUCKET_SIZE];
|
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
|
|
|
TypeWrapper wrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(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)
|
|
|
|
{
|
2004-09-27 14:17:34 +04:00
|
|
|
if(x.GetType() == ClassLoaderWrapper.LoadClassCritical("java.lang.reflect.InvocationTargetException").TypeAsExceptionType)
|
|
|
|
{
|
|
|
|
x = x.InnerException;
|
|
|
|
}
|
2004-11-29 16:58:21 +03:00
|
|
|
SetPendingException(pEnv, Util.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
|
|
|
{
|
2004-10-19 17:43:55 +04:00
|
|
|
return pEnv->MakeLocalRef(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)
|
|
|
|
{
|
2004-10-19 17:43:55 +04:00
|
|
|
object objClass = IKVM.Runtime.Util.GetClassFromObject(pEnv->UnwrapRef(obj));
|
2004-09-09 15:17:55 +04:00
|
|
|
TypeWrapper w1 = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz));
|
|
|
|
TypeWrapper w2 = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(objClass);
|
|
|
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
TypeWrapper wrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz));
|
|
|
|
wrapper.Finish();
|
2005-01-03 11:26:21 +03:00
|
|
|
MethodWrapper mw = wrapper.GetMethodWrapper(StringFromUTF8(name), StringFromUTF8(sig).Replace('/', '.'), true);
|
2004-09-09 15:17:55 +04:00
|
|
|
if(mw != null)
|
2004-08-30 19:56:23 +04:00
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
if(mw.IsStatic == isstatic)
|
|
|
|
{
|
|
|
|
mw.Link();
|
|
|
|
return mw.Cookie;
|
|
|
|
}
|
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)
|
|
|
|
{
|
|
|
|
return (jbyte)(sbyte)o;
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
return (jbyte)(sbyte)o;
|
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
|
|
|
TypeWrapper wrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz));
|
|
|
|
wrapper.Finish();
|
2004-10-04 23:30:53 +04:00
|
|
|
FieldWrapper fw = wrapper.GetFieldWrapper(StringFromUTF8(name), StringFromUTF8(sig).Replace('/', '.'));
|
2004-09-09 15:17:55 +04:00
|
|
|
if(fw != null)
|
|
|
|
{
|
|
|
|
if(fw.IsStatic == isstatic)
|
|
|
|
{
|
|
|
|
// TODO fw.Link()
|
|
|
|
return fw.Cookie;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetPendingException(pEnv, JavaException.NoSuchFieldError(StringFromUTF8(name)));
|
|
|
|
}
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
return (jbyte)(sbyte)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)
|
|
|
|
{
|
|
|
|
SetFieldValue(fieldID, pEnv->UnwrapRef(obj), (sbyte)val);
|
|
|
|
}
|
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)
|
|
|
|
{
|
|
|
|
return (jbyte)(sbyte)o;
|
|
|
|
}
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
return (jbyte)(sbyte)GetFieldValue(fieldID, null);
|
|
|
|
}
|
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)
|
|
|
|
{
|
|
|
|
SetFieldValue(fieldID, null, (sbyte)val);
|
|
|
|
}
|
|
|
|
|
|
|
|
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[]
|
|
|
|
Array array = Array.CreateInstance(IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz)).TypeAsArrayType, len);
|
|
|
|
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
|
|
|
|
{
|
|
|
|
return pEnv->MakeLocalRef(new sbyte[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 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)
|
|
|
|
{
|
|
|
|
sbyte[] b = (sbyte[])pEnv->UnwrapRef(array);
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
sbyte[] b = (sbyte[])pEnv->UnwrapRef(array);
|
|
|
|
for(int i = 0; i < b.Length; i++)
|
|
|
|
{
|
|
|
|
b[i] = (sbyte)elems[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
|
|
|
sbyte[] b = (sbyte[])pEnv->UnwrapRef(array);
|
|
|
|
sbyte* p = (sbyte*)(void*)buf;
|
|
|
|
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
|
|
|
|
{
|
|
|
|
sbyte[] b = (sbyte[])pEnv->UnwrapRef(array);
|
|
|
|
sbyte* p = (sbyte*)(void*)buf;
|
|
|
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
TypeWrapper wrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz));
|
|
|
|
wrapper.Finish();
|
|
|
|
for(int i = 0; i < nMethods; i++)
|
2004-08-30 19:56:23 +04:00
|
|
|
{
|
2004-11-24 13:57:11 +03:00
|
|
|
// TODO this won't work when we're putting the JNI methods in jniproxy.dll
|
|
|
|
FieldInfo fi = wrapper.TypeAsTBD.GetField(JNI.METHOD_PTR_FIELD_PREFIX + StringFromUTF8(methods[i].name) + StringFromUTF8(methods[i].signature).Replace('/', '.') + ">", BindingFlags.Static | BindingFlags.NonPublic);
|
2004-09-09 15:17:55 +04:00
|
|
|
if(fi == null)
|
|
|
|
{
|
|
|
|
SetPendingException(pEnv, JavaException.NoSuchMethodError(StringFromUTF8(methods[i].name)));
|
|
|
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
TypeWrapper wrapper = IKVM.NativeCode.java.lang.VMClass.getWrapperFromClass(pEnv->UnwrapRef(clazz));
|
|
|
|
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
|
|
|
{
|
2004-11-23 20:46:39 +03:00
|
|
|
if(fi.Name.StartsWith(JNI.METHOD_PTR_FIELD_PREFIX))
|
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();
|
|
|
|
if(type == typeof(sbyte) || type == typeof(bool))
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if(type == typeof(short) || type == typeof(char))
|
|
|
|
{
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
else if(type == typeof(int) || type == typeof(float))
|
|
|
|
{
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
else if(type == typeof(long) || type == typeof(double))
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-09 15:17:55 +04:00
|
|
|
internal static IntPtr GetPrimitiveArrayCritical(JNIEnv* pEnv, IntPtr array, IntPtr isCopy)
|
2004-08-17 13:05:21 +04:00
|
|
|
{
|
2004-08-30 19:56:23 +04:00
|
|
|
Array ar = (Array)pEnv->UnwrapRef(array);
|
|
|
|
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++;
|
|
|
|
}
|
2004-09-09 15:17:55 +04:00
|
|
|
if(isCopy != IntPtr.Zero)
|
|
|
|
{
|
|
|
|
*((sbyte*)(void*)isCopy) = JNI_TRUE;
|
|
|
|
}
|
|
|
|
return 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
|
|
|
}
|
|
|
|
|
2004-09-09 15:17:55 +04:00
|
|
|
internal static void ReleasePrimitiveArrayCritical(JNIEnv* pEnv, IntPtr array, IntPtr carray, int mode)
|
2004-08-30 19:56:23 +04:00
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
if(mode == 0 || mode == JNI_COMMIT)
|
|
|
|
{
|
|
|
|
Array ar = (Array)pEnv->UnwrapRef(array);
|
|
|
|
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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
JniMem.Free(carray);
|
2004-08-30 19:56:23 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-09 15:17:55 +04:00
|
|
|
internal static IntPtr GetStringCritical(JNIEnv* pEnv, IntPtr str, IntPtr 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
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
if(isCopy != IntPtr.Zero)
|
2004-09-05 13:37:58 +04:00
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
*((sbyte*)(void*)isCopy) = JNI_TRUE;
|
2004-09-05 13:37:58 +04:00
|
|
|
}
|
2004-09-09 15:17:55 +04:00
|
|
|
return Marshal.StringToHGlobalUni(s);
|
2004-09-05 13:37:58 +04:00
|
|
|
}
|
2004-09-09 15:17:55 +04:00
|
|
|
SetPendingException(pEnv, JavaException.NullPointerException());
|
|
|
|
return IntPtr.Zero;
|
2004-09-05 13:37:58 +04:00
|
|
|
}
|
|
|
|
|
2004-09-09 15:17:55 +04:00
|
|
|
internal static void ReleaseStringCritical(JNIEnv* pEnv, IntPtr str, IntPtr cstring)
|
2004-09-05 13:37:58 +04:00
|
|
|
{
|
2004-09-09 15:17:55 +04:00
|
|
|
Marshal.FreeHGlobal(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++)
|
|
|
|
{
|
|
|
|
if(!GlobalRefs.weakRefs[i].IsAllocated)
|
|
|
|
{
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2004-09-09 15:17:55 +04:00
|
|
|
internal static sbyte 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)
|
|
|
|
{
|
2004-11-29 16:58:21 +03:00
|
|
|
SetPendingException(pEnv, Util.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)
|
|
|
|
{
|
2004-11-29 16:58:21 +03:00
|
|
|
SetPendingException(pEnv, Util.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)
|
|
|
|
{
|
2004-11-29 16:58:21 +03:00
|
|
|
SetPendingException(pEnv, Util.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
|
|
|
// MONOBUG Marshal.AllocHGlobal returns a null pointer if we try to allocate zero bytes
|
2004-10-04 23:30:53 +04:00
|
|
|
// (as of Mono 1.0.2 this shouldn't be necessary anymore)
|
2004-09-09 15:17:55 +04:00
|
|
|
if(cb == 0)
|
|
|
|
{
|
|
|
|
cb = 1;
|
|
|
|
}
|
|
|
|
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
|
|
|
}
|