static void RaiseException(TextWriter o, JniFunction entry) { if (!entry.Throws) { return; } o.WriteLine(); o.WriteLine("\t\t\tException __e = AndroidEnvironment.GetExceptionForLastThrowable ();"); o.WriteLine("\t\t\tif (__e != null)"); o.WriteLine("\t\t\t\tExceptionDispatchInfo.Capture (__e).Throw ();"); o.WriteLine(); }
static void CreateDelegate(TextWriter o, JniFunction entry) { StringBuilder builder = new StringBuilder(); StringBuilder name = new StringBuilder(); bool has_char_array = false; Func <string, string> FixupType = t => t.Replace("*", "Ref").Replace("[]", "Array").Replace(" ", ""); builder.AppendFormat("\t\tinternal unsafe delegate {0} % (IntPtr env", entry.ReturnType.ManagedType, entry.Name); name.Append("IntPtr"); for (int i = 0; i < entry.Parameters.Length; i++) { if (i >= 0) { builder.Append(", "); builder.AppendFormat("{0} {1}", entry.Parameters [i].Type.ManagedType, entry.Parameters [i].Name); } if (entry.Parameters [i].Type.ManagedType == "va_list") { return; } if (entry.Parameters [i].Type.ManagedType == "char[]") { has_char_array = true; } name.AppendFormat("_").Append(FixupType(entry.Parameters [i].Type.ManagedType)); } name.Append("_").Append(FixupType(entry.ReturnType.ManagedType)); name.Append("_Delegate"); builder.Append(");\n"); builder.Replace("%", name.ToString()); entry.Delegate = "JNIEnv." + name.ToString(); if (created_delegates.Contains(name.ToString())) { return; } created_delegates.Add(name.ToString()); if (entry.Name == "NewString" || has_char_array) { o.WriteLine("\t\t[UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl, CharSet=CharSet.Unicode)]"); } o.Write(builder.ToString()); }
static void CreateDelegate(TextWriter o, JniFunction entry) { StringBuilder builder = new StringBuilder (); StringBuilder name = new StringBuilder (); bool has_char_array = false; Func<string, string> FixupType = t => t.Replace ("*", "Ref").Replace ("[]", "Array").Replace (" ", ""); builder.AppendFormat ("\t\tinternal unsafe delegate {0} % (IntPtr env", entry.ReturnType.ManagedType, entry.Name); name.Append ("IntPtr"); for (int i = 0; i < entry.Parameters.Length; i++) { if (i >= 0) { builder.Append (", "); builder.AppendFormat ("{0} {1}", entry.Parameters [i].Type.ManagedType, entry.Parameters [i].Name); } if (entry.Parameters [i].Type.ManagedType == "va_list") return; if (entry.Parameters [i].Type.ManagedType == "char[]") has_char_array = true; name.AppendFormat ("_").Append (FixupType (entry.Parameters [i].Type.ManagedType)); } name.Append ("_").Append (FixupType (entry.ReturnType.ManagedType)); name.Append ("_Delegate"); builder.Append (");\n"); builder.Replace ("%", name.ToString ()); entry.Delegate = "JNIEnv." + name.ToString (); if (created_delegates.Contains (name.ToString ())) return; created_delegates.Add (name.ToString ()); if (entry.Name == "NewString" || has_char_array) o.WriteLine ("\t\t[UnmanagedFunctionPointerAttribute (CallingConvention.Cdecl, CharSet=CharSet.Unicode)]"); o.Write (builder.ToString ()); }
static void WriteJniFunctionParameters(TextWriter o, JniFunction entry, bool generateParamsOverload) { o.Write("("); for (int i = 0; i < entry.Parameters.Length; i++) { if (i > 0) { o.Write(", "); } if (!entry.Parameters [i].IsParamArray) { o.Write("{0} {1}", entry.Parameters [i].Type.ManagedType, Escape(entry.Parameters [i].Name)); } else if (generateParamsOverload && i == entry.Parameters.Length - 1) { o.Write("{0} {1}", entry.Parameters [i].Type.ManagedType, Escape(entry.Parameters [i].Name)); } else { o.Write("params {0} {1}", entry.Parameters [i].Type.ManagedType.Replace("*", "[]"), Escape(entry.Parameters [i].Name)); } } o.WriteLine(")"); }
static bool GenerateDefaultJavaInteropForwarder(TextWriter o, JniFunction entry, bool generateParamsOverload) { if (!useJavaInterop) { return(false); } switch (entry.Name) { // These must be hand-bound case "GetBooleanArrayRegion": case "GetJavaVM": case "GetStringChars": case "GetVersion": case "RegisterNatives": case "ReleaseStringChars": case "SetBooleanArrayRegion": return(true); } o.Write("\t\t{0} static unsafe {1} {2} ", entry.Visibility, entry.ReturnType.ManagedType, entry.ApiName); bool is_void = entry.ReturnType.ManagedType == "void"; var lastName = entry.Parameters.Length == 0 ? "" : entry.Parameters[entry.Parameters.Length - 1].Name; WriteJniFunctionParameters(o, entry, generateParamsOverload); o.WriteLine("\t\t{"); o.Write("\t\t\t"); if (!is_void) { o.Write("return "); } var n = entry.Name; if (n.StartsWith("Call")) { n = n.TrimEnd(new[] { 'A' }); } o.Write("JniEnvironment.{0}.{1} (", entry.DeclaringType, n); for (int i = 0; i < entry.Parameters.Length; i++) { if (i > 0) { o.Write(", "); } if (entry.Parameters [i].Type.ManagedType.StartsWith("out ")) { o.Write("out "); } if (entry.Parameters [i].Type.ManagedType == "JValue*") { o.Write("(JniArgumentValue*) " + Escape(entry.Parameters [i].Name)); } else if (IsObjectReferenceType(entry.Parameters [i].Type)) { o.Write(string.Format("new JniObjectReference ({0})", Escape(entry.Parameters [i].Name))); } else if (IsMemberID(entry.Parameters [i].Type)) { string ctorFormat = null; switch (entry.Parameters [i].Type.Type) { case "jfieldID": ctorFormat = "new JniFieldInfo ({0}, isStatic: false)"; break; case "jmethodID": ctorFormat = "new JniMethodInfo ({0}, isStatic: false)"; break; case "jstaticfieldID": ctorFormat = "new JniFieldInfo ({0}, isStatic: true)"; break; case "jstaticmethodID": ctorFormat = "new JniMethodInfo ({0}, isStatic: true)"; break; default: throw new NotSupportedException("Don't know how to deal with: " + entry.Parameters [i].Type.Type); } o.Write(string.Format(ctorFormat, Escape(entry.Parameters [i].Name))); } else { o.Write(Escape(entry.Parameters [i].Name)); } } o.Write(")"); if (IsObjectReferenceType(entry.ReturnType)) { o.Write(".Handle"); } if (IsMemberID(entry.ReturnType)) { o.Write(".ID"); } o.WriteLine(";"); o.WriteLine("\t\t}"); if (!generateParamsOverload) { return(true); } o.WriteLine(); o.Write("\t\t{0} static {1}{2} {3} ", entry.Visibility, "unsafe ", entry.ReturnType.ManagedType, entry.ApiName); WriteJniFunctionParameters(o, entry, false); o.WriteLine("\t\t{"); o.WriteLine("\t\t\tfixed (JValue* __p = {0}) {{", Escape(entry.Parameters [entry.Parameters.Length - 1].Name)); o.WriteLine("\t\t\t\t{0}{1} ({2}, __p);", is_void ? "" : "return ", entry.ApiName, string.Join(", ", entry.Parameters.Take(entry.Parameters.Length - 1).Select(p => Escape(p.Name)))); o.WriteLine("\t\t\t}"); o.WriteLine("\t\t}"); return(true); }
static void GenerateDefaultJniFunction(TextWriter o, JniFunction entry) { bool generateParamsOverload = entry.Parameters.Length > 1 && entry.Parameters [entry.Parameters.Length - 1].IsParamArray && entry.Parameters [entry.Parameters.Length - 1].Type.ManagedType == "JValue*"; if (GenerateDefaultJavaInteropForwarder(o, entry, generateParamsOverload)) { return; } o.Write("\t\t{0} static {1}{2} {3} ", entry.Visibility, generateParamsOverload ? "unsafe " : "", entry.ReturnType.ManagedType, entry.ApiName); bool is_void = entry.ReturnType.ManagedType == "void"; var lastName = entry.Parameters.Length == 0 ? "" : entry.Parameters[entry.Parameters.Length - 1].Name; WriteJniFunctionParameters(o, entry, generateParamsOverload); o.WriteLine("\t\t{"); NullCheckParameters(o, entry.Parameters); o.Write("\t\t\t"); if (!is_void) { o.Write("{0} tmp = ", entry.ReturnType.ManagedType); } o.Write("Env.{0} (Handle", entry.Name); for (int i = 0; i < entry.Parameters.Length; i++) { o.Write(", "); if (entry.Parameters [i].Type.ManagedType.StartsWith("out ")) { o.Write("out "); } o.Write(Escape(entry.Parameters [i].Name)); } o.WriteLine(");"); RaiseException(o, entry); if (is_void) { } else if (entry.ReturnType.ManagedType == "IntPtr" && entry.ReturnType.Type.StartsWith("j") && !entry.ReturnType.Type.EndsWith("ID")) { o.WriteLine("\t\t\treturn LogCreateLocalRef (tmp);"); } else { o.WriteLine("\t\t\treturn tmp;"); } o.WriteLine("\t\t}"); if (!generateParamsOverload) { return; } o.WriteLine(); o.Write("\t\t{0} static {1}{2} {3} ", entry.Visibility, "unsafe ", entry.ReturnType.ManagedType, entry.ApiName); WriteJniFunctionParameters(o, entry, false); o.WriteLine("\t\t{"); o.WriteLine("\t\t\tfixed (JValue* __p = {0}) {{", Escape(entry.Parameters [entry.Parameters.Length - 1].Name)); o.WriteLine("\t\t\t\t{0}{1} ({2}, __p);", is_void ? "" : "return ", entry.ApiName, string.Join(", ", entry.Parameters.Take(entry.Parameters.Length - 1).Select(p => Escape(p.Name)))); o.WriteLine("\t\t\t}"); o.WriteLine("\t\t}"); }
static string Initialize(JniFunction e, string prefix) { //return String.Format ("{2}{0} = GetDelegate<{1}>(JniEnv.{0});", e.Name, e.Delegate, prefix); return(String.Format("{2}{0} = ({1}) Marshal.GetDelegateForFunctionPointer (JniEnv.{0}, typeof ({1}));", e.Name, e.Delegate, prefix)); }
static void WriteJniFunctionParameters(TextWriter o, JniFunction entry, bool generateParamsOverload) { o.Write ("("); for (int i = 0; i < entry.Parameters.Length; i++) { if (i > 0) o.Write (", "); if (!entry.Parameters [i].IsParamArray) { o.Write ("{0} {1}", entry.Parameters [i].Type.ManagedType, Escape (entry.Parameters [i].Name)); } else if (generateParamsOverload && i == entry.Parameters.Length -1) { o.Write ("{0} {1}", entry.Parameters [i].Type.ManagedType, Escape (entry.Parameters [i].Name)); } else { o.Write ("params {0} {1}", entry.Parameters [i].Type.ManagedType.Replace ("*", "[]"), Escape (entry.Parameters [i].Name)); } } o.WriteLine (")"); }
static void RaiseException(TextWriter o, JniFunction entry) { if (!entry.Throws) return; o.WriteLine (); o.WriteLine ("\t\t\tException __e = AndroidEnvironment.GetExceptionForLastThrowable ();"); o.WriteLine ("\t\t\tif (__e != null)"); o.WriteLine ("\t\t\t\tExceptionDispatchInfo.Capture (__e).Throw ();"); o.WriteLine (); }
static string Initialize(JniFunction e, string prefix) { //return String.Format ("{2}{0} = GetDelegate<{1}>(JniEnv.{0});", e.Name, e.Delegate, prefix); return String.Format ("{2}{0} = ({1}) Marshal.GetDelegateForFunctionPointer (JniEnv.{0}, typeof ({1}));", e.Name, e.Delegate, prefix); }
static void GenerateDefaultJniFunction(TextWriter o, JniFunction entry) { bool generateParamsOverload = entry.Parameters.Length > 1 && entry.Parameters [entry.Parameters.Length-1].IsParamArray && entry.Parameters [entry.Parameters.Length-1].Type.ManagedType == "JValue*"; if (GenerateDefaultJavaInteropForwarder (o, entry, generateParamsOverload)) return; o.Write ("\t\t{0} static {1}{2} {3} ", entry.Visibility, generateParamsOverload ? "unsafe " : "", entry.ReturnType.ManagedType, entry.ApiName); bool is_void = entry.ReturnType.ManagedType == "void"; var lastName = entry.Parameters.Length == 0 ? "" : entry.Parameters[entry.Parameters.Length - 1].Name; WriteJniFunctionParameters (o, entry, generateParamsOverload); o.WriteLine ("\t\t{"); NullCheckParameters (o, entry.Parameters); o.Write ("\t\t\t"); if (!is_void) o.Write ("{0} tmp = ", entry.ReturnType.ManagedType); o.Write ("Env.{0} (Handle", entry.Name); for (int i = 0; i < entry.Parameters.Length; i++) { o.Write (", "); if (entry.Parameters [i].Type.ManagedType.StartsWith ("out ")) o.Write ("out "); o.Write (Escape (entry.Parameters [i].Name)); } o.WriteLine (");"); RaiseException (o, entry); if (is_void) { } else if (entry.ReturnType.ManagedType == "IntPtr" && entry.ReturnType.Type.StartsWith ("j") && !entry.ReturnType.Type.EndsWith ("ID")) { o.WriteLine ("\t\t\treturn LogCreateLocalRef (tmp);"); } else { o.WriteLine ("\t\t\treturn tmp;"); } o.WriteLine ("\t\t}"); if (!generateParamsOverload) return; o.WriteLine (); o.Write ("\t\t{0} static {1}{2} {3} ", entry.Visibility, "unsafe ", entry.ReturnType.ManagedType, entry.ApiName); WriteJniFunctionParameters (o, entry, false); o.WriteLine ("\t\t{"); o.WriteLine ("\t\t\tfixed (JValue* __p = {0}) {{", Escape (entry.Parameters [entry.Parameters.Length-1].Name)); o.WriteLine ("\t\t\t\t{0}{1} ({2}, __p);", is_void ? "" : "return ", entry.ApiName, string.Join (", ", entry.Parameters.Take (entry.Parameters.Length-1).Select (p => Escape (p.Name)))); o.WriteLine ("\t\t\t}"); o.WriteLine ("\t\t}"); }
static bool GenerateDefaultJavaInteropForwarder(TextWriter o, JniFunction entry, bool generateParamsOverload) { if (!useJavaInterop) return false; switch (entry.Name) { // These must be hand-bound case "GetBooleanArrayRegion": case "GetJavaVM": case "GetStringChars": case "GetVersion": case "RegisterNatives": case "ReleaseStringChars": case "SetBooleanArrayRegion": return true; } o.Write ("\t\t{0} static unsafe {1} {2} ", entry.Visibility, entry.ReturnType.ManagedType, entry.ApiName); bool is_void = entry.ReturnType.ManagedType == "void"; var lastName = entry.Parameters.Length == 0 ? "" : entry.Parameters[entry.Parameters.Length - 1].Name; WriteJniFunctionParameters (o, entry, generateParamsOverload); o.WriteLine ("\t\t{"); o.Write ("\t\t\t"); if (!is_void) o.Write ("return "); var n = entry.Name; if (n.StartsWith ("Call")) n = n.TrimEnd (new[]{'A'}); o.Write ("JniEnvironment.{0}.{1} (", entry.DeclaringType, n); for (int i = 0; i < entry.Parameters.Length; i++) { if (i > 0) o.Write (", "); if (entry.Parameters [i].Type.ManagedType.StartsWith ("out ")) o.Write ("out "); if (entry.Parameters [i].Type.ManagedType == "JValue*") o.Write ("(JniArgumentValue*) " + Escape (entry.Parameters [i].Name)); else if (IsObjectReferenceType (entry.Parameters [i].Type)) o.Write (string.Format ("new JniObjectReference ({0})", Escape (entry.Parameters [i].Name))); else if (IsMemberID (entry.Parameters [i].Type)) { string ctorFormat = null; switch (entry.Parameters [i].Type.Type) { case "jfieldID": ctorFormat = "new JniFieldInfo ({0}, isStatic: false)"; break; case "jmethodID": ctorFormat = "new JniMethodInfo ({0}, isStatic: false)"; break; case "jstaticfieldID": ctorFormat = "new JniFieldInfo ({0}, isStatic: true)"; break; case "jstaticmethodID": ctorFormat = "new JniMethodInfo ({0}, isStatic: true)"; break; default: throw new NotSupportedException ("Don't know how to deal with: " + entry.Parameters [i].Type.Type); } o.Write (string.Format (ctorFormat, Escape (entry.Parameters [i].Name))); } else o.Write (Escape (entry.Parameters [i].Name)); } o.Write (")"); if (IsObjectReferenceType (entry.ReturnType)) o.Write (".Handle"); if (IsMemberID (entry.ReturnType)) o.Write (".ID"); o.WriteLine (";"); o.WriteLine ("\t\t}"); if (!generateParamsOverload) return true; o.WriteLine (); o.Write ("\t\t{0} static {1}{2} {3} ", entry.Visibility, "unsafe ", entry.ReturnType.ManagedType, entry.ApiName); WriteJniFunctionParameters (o, entry, false); o.WriteLine ("\t\t{"); o.WriteLine ("\t\t\tfixed (JValue* __p = {0}) {{", Escape (entry.Parameters [entry.Parameters.Length-1].Name)); o.WriteLine ("\t\t\t\t{0}{1} ({2}, __p);", is_void ? "" : "return ", entry.ApiName, string.Join (", ", entry.Parameters.Take (entry.Parameters.Length-1).Select (p => Escape (p.Name)))); o.WriteLine ("\t\t\t}"); o.WriteLine ("\t\t}"); return true; }