mirror of
https://github.com/Ryujinx/GtkSharp.git
synced 2024-12-26 07:15:34 +00:00
2ba496479f
* generator/*.cs: Add a LogWriter class which formats warnings consistently on the console. Supports the concept of non-fatal validation warnings, since it doesn't rely on the unrolling of the validation stack to associate a warning to a given type. Main purpose was to add a non-fatal warning for missing element_type attributes on list return values, though it results in cleaner log output, and also updates some warning messages to be more helpful in how to resolve them.
300 lines
9.7 KiB
C#
300 lines
9.7 KiB
C#
// GtkSharp.Generation.CallbackGen.cs - The Callback Generatable.
|
|
//
|
|
// Author: Mike Kestner <mkestner@novell.com>
|
|
//
|
|
// Copyright (c) 2002-2003 Mike Kestner
|
|
// Copyright (c) 2007 Novell, Inc.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of version 2 of the GNU General Public
|
|
// License as published by the Free Software Foundation.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public
|
|
// License along with this program; if not, write to the
|
|
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
// Boston, MA 02111-1307, USA.
|
|
|
|
|
|
namespace GtkSharp.Generation {
|
|
|
|
using System;
|
|
using System.IO;
|
|
using System.Xml;
|
|
|
|
public class CallbackGen : GenBase, IAccessor {
|
|
|
|
private Parameters parms;
|
|
private Signature sig = null;
|
|
private ReturnValue retval;
|
|
private bool valid = true;
|
|
|
|
public CallbackGen (XmlElement ns, XmlElement elem) : base (ns, elem)
|
|
{
|
|
retval = new ReturnValue (elem ["return-type"]);
|
|
parms = new Parameters (elem ["parameters"]);
|
|
parms.HideData = true;
|
|
}
|
|
|
|
public override string DefaultValue {
|
|
get { return "null"; }
|
|
}
|
|
|
|
public override bool Validate ()
|
|
{
|
|
valid = true;
|
|
LogWriter log = new LogWriter ();
|
|
log.Type = QualifiedName;
|
|
if (!retval.Validate (log) || !parms.Validate (log)) {
|
|
Statistics.ThrottledCount++;
|
|
valid = false;
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
public string InvokerName {
|
|
get {
|
|
if (!valid)
|
|
return String.Empty;
|
|
return NS + "Sharp." + Name + "Invoker";
|
|
}
|
|
}
|
|
|
|
public override string MarshalType {
|
|
get {
|
|
if (valid)
|
|
return NS + "Sharp." + Name + "Native";
|
|
else
|
|
return "";
|
|
}
|
|
}
|
|
|
|
public override string CallByName (string var_name)
|
|
{
|
|
return var_name + ".NativeDelegate";
|
|
}
|
|
|
|
public override string FromNative (string var)
|
|
{
|
|
return NS + "Sharp." + Name + "Wrapper.GetManagedDelegate (" + var + ")";
|
|
}
|
|
|
|
public void WriteAccessors (StreamWriter sw, string indent, string var)
|
|
{
|
|
sw.WriteLine (indent + "get {");
|
|
sw.WriteLine (indent + "\treturn " + FromNative (var) + ";");
|
|
sw.WriteLine (indent + "}");
|
|
}
|
|
|
|
string CastFromInt (string type)
|
|
{
|
|
return type != "int" ? "(" + type + ") " : "";
|
|
}
|
|
|
|
string InvokeString {
|
|
get {
|
|
if (parms.Count == 0)
|
|
return String.Empty;
|
|
|
|
string[] result = new string [parms.Count];
|
|
for (int i = 0; i < parms.Count; i++) {
|
|
Parameter p = parms [i];
|
|
IGeneratable igen = p.Generatable;
|
|
|
|
if (i > 0 && parms [i - 1].IsString && p.IsLength) {
|
|
string string_name = parms [i - 1].Name;
|
|
result[i] = igen.CallByName (CastFromInt (p.CSType) + "System.Text.Encoding.UTF8.GetByteCount (" + string_name + ")");
|
|
continue;
|
|
}
|
|
|
|
p.CallName = p.Name;
|
|
result [i] = p.CallString;
|
|
if (p.IsUserData)
|
|
result [i] = "__data";
|
|
}
|
|
|
|
return String.Join (", ", result);
|
|
}
|
|
}
|
|
|
|
MethodBody body;
|
|
|
|
void GenInvoker (GenerationInfo gen_info, StreamWriter sw)
|
|
{
|
|
if (sig == null)
|
|
sig = new Signature (parms);
|
|
|
|
sw.WriteLine ("\tinternal class " + Name + "Invoker {");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\t" + Name + "Native native_cb;");
|
|
sw.WriteLine ("\t\tIntPtr __data;");
|
|
sw.WriteLine ("\t\tGLib.DestroyNotify __notify;");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\t~" + Name + "Invoker ()");
|
|
sw.WriteLine ("\t\t{");
|
|
sw.WriteLine ("\t\t\tif (__notify == null)");
|
|
sw.WriteLine ("\t\t\t\treturn;");
|
|
sw.WriteLine ("\t\t\t__notify (__data);");
|
|
sw.WriteLine ("\t\t}");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\tinternal " + Name + "Invoker (" + Name + "Native native_cb) : this (native_cb, IntPtr.Zero, null) {}");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\tinternal " + Name + "Invoker (" + Name + "Native native_cb, IntPtr data) : this (native_cb, data, null) {}");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\tinternal " + Name + "Invoker (" + Name + "Native native_cb, IntPtr data, GLib.DestroyNotify notify)");
|
|
sw.WriteLine ("\t\t{");
|
|
sw.WriteLine ("\t\t\tthis.native_cb = native_cb;");
|
|
sw.WriteLine ("\t\t\t__data = data;");
|
|
sw.WriteLine ("\t\t\t__notify = notify;");
|
|
sw.WriteLine ("\t\t}");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\tinternal " + QualifiedName + " Handler {");
|
|
sw.WriteLine ("\t\t\tget {");
|
|
sw.WriteLine ("\t\t\t\treturn new " + QualifiedName + "(InvokeNative);");
|
|
sw.WriteLine ("\t\t\t}");
|
|
sw.WriteLine ("\t\t}");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\t" + retval.CSType + " InvokeNative (" + sig + ")");
|
|
sw.WriteLine ("\t\t{");
|
|
body.Initialize (gen_info);
|
|
string call = "native_cb (" + InvokeString + ")";
|
|
if (retval.IsVoid)
|
|
sw.WriteLine ("\t\t\t" + call + ";");
|
|
else
|
|
sw.WriteLine ("\t\t\t" + retval.CSType + " __result = " + retval.FromNative (call) + ";");
|
|
body.Finish (sw, String.Empty);
|
|
if (!retval.IsVoid)
|
|
sw.WriteLine ("\t\t\treturn __result;");
|
|
sw.WriteLine ("\t\t}");
|
|
sw.WriteLine ("\t}");
|
|
sw.WriteLine ();
|
|
}
|
|
|
|
public string GenWrapper (GenerationInfo gen_info)
|
|
{
|
|
string wrapper = Name + "Native";
|
|
string qualname = MarshalType;
|
|
|
|
if (!Validate ())
|
|
return String.Empty;
|
|
|
|
body = new MethodBody (parms);
|
|
|
|
StreamWriter save_sw = gen_info.Writer;
|
|
StreamWriter sw = gen_info.Writer = gen_info.OpenStream (qualname);
|
|
|
|
sw.WriteLine ("namespace " + NS + "Sharp {");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\tusing System;");
|
|
sw.WriteLine ("\tusing System.Runtime.InteropServices;");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("#region Autogenerated code");
|
|
sw.WriteLine ("\t[UnmanagedFunctionPointer (CallingConvention.Cdecl)]");
|
|
sw.WriteLine ("\tinternal delegate " + retval.MarshalType + " " + wrapper + "(" + parms.ImportSignature + ");");
|
|
sw.WriteLine ();
|
|
GenInvoker (gen_info, sw);
|
|
sw.WriteLine ("\tinternal class " + Name + "Wrapper {");
|
|
sw.WriteLine ();
|
|
ManagedCallString call = new ManagedCallString (parms);
|
|
sw.WriteLine ("\t\tpublic " + retval.MarshalType + " NativeCallback (" + parms.ImportSignature + ")");
|
|
sw.WriteLine ("\t\t{");
|
|
string unconditional = call.Unconditional ("\t\t\t");
|
|
if (unconditional.Length > 0)
|
|
sw.WriteLine (unconditional);
|
|
sw.WriteLine ("\t\t\ttry {");
|
|
string call_setup = call.Setup ("\t\t\t\t");
|
|
if (call_setup.Length > 0)
|
|
sw.WriteLine (call_setup);
|
|
if (retval.CSType == "void")
|
|
sw.WriteLine ("\t\t\t\tmanaged ({0});", call);
|
|
else
|
|
sw.WriteLine ("\t\t\t\t{0} __ret = managed ({1});", retval.CSType, call);
|
|
string finish = call.Finish ("\t\t\t\t");
|
|
if (finish.Length > 0)
|
|
sw.WriteLine (finish);
|
|
sw.WriteLine ("\t\t\t\tif (release_on_call)\n\t\t\t\t\tgch.Free ();");
|
|
if (retval.CSType != "void")
|
|
sw.WriteLine ("\t\t\t\treturn {0};", retval.ToNative ("__ret"));
|
|
|
|
/* If the function expects one or more "out" parameters(error parameters are excluded) or has a return value different from void and bool, exceptions
|
|
* thrown in the managed function have to be considered fatal meaning that an exception is to be thrown and the function call cannot not return
|
|
*/
|
|
bool fatal = (retval.MarshalType != "void" && retval.MarshalType != "bool") || call.HasOutParam;
|
|
sw.WriteLine ("\t\t\t} catch (Exception e) {");
|
|
sw.WriteLine ("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (e, " + (fatal ? "true" : "false") + ");");
|
|
if (fatal) {
|
|
sw.WriteLine ("\t\t\t\t// NOTREACHED: Above call does not return.");
|
|
sw.WriteLine ("\t\t\t\tthrow e;");
|
|
} else if (retval.MarshalType == "bool") {
|
|
sw.WriteLine ("\t\t\t\treturn false;");
|
|
}
|
|
sw.WriteLine ("\t\t\t}");
|
|
sw.WriteLine ("\t\t}");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\tbool release_on_call = false;");
|
|
sw.WriteLine ("\t\tGCHandle gch;");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\tpublic void PersistUntilCalled ()");
|
|
sw.WriteLine ("\t\t{");
|
|
sw.WriteLine ("\t\t\trelease_on_call = true;");
|
|
sw.WriteLine ("\t\t\tgch = GCHandle.Alloc (this);");
|
|
sw.WriteLine ("\t\t}");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\tinternal " + wrapper + " NativeDelegate;");
|
|
sw.WriteLine ("\t\t" + NS + "." + Name + " managed;");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\tpublic " + Name + "Wrapper (" + NS + "." + Name + " managed)");
|
|
sw.WriteLine ("\t\t{");
|
|
sw.WriteLine ("\t\t\tthis.managed = managed;");
|
|
sw.WriteLine ("\t\t\tif (managed != null)");
|
|
sw.WriteLine ("\t\t\t\tNativeDelegate = new " + wrapper + " (NativeCallback);");
|
|
sw.WriteLine ("\t\t}");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t\tpublic static " + NS + "." + Name + " GetManagedDelegate (" + wrapper + " native)");
|
|
sw.WriteLine ("\t\t{");
|
|
sw.WriteLine ("\t\t\tif (native == null)");
|
|
sw.WriteLine ("\t\t\t\treturn null;");
|
|
sw.WriteLine ("\t\t\t" + Name + "Wrapper wrapper = (" + Name + "Wrapper) native.Target;");
|
|
sw.WriteLine ("\t\t\tif (wrapper == null)");
|
|
sw.WriteLine ("\t\t\t\treturn null;");
|
|
sw.WriteLine ("\t\t\treturn wrapper.managed;");
|
|
sw.WriteLine ("\t\t}");
|
|
sw.WriteLine ("\t}");
|
|
sw.WriteLine ("#endregion");
|
|
sw.WriteLine ("}");
|
|
sw.Close ();
|
|
gen_info.Writer = save_sw;
|
|
return NS + "Sharp." + Name + "Wrapper";
|
|
}
|
|
|
|
public override void Generate (GenerationInfo gen_info)
|
|
{
|
|
gen_info.CurrentType = QualifiedName;
|
|
|
|
sig = new Signature (parms);
|
|
|
|
StreamWriter sw = gen_info.OpenStream (Name);
|
|
|
|
sw.WriteLine ("namespace " + NS + " {");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\tusing System;");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("\t{0} delegate " + retval.CSType + " " + Name + "(" + sig.ToString() + ");", IsInternal ? "internal" : "public");
|
|
sw.WriteLine ();
|
|
sw.WriteLine ("}");
|
|
|
|
sw.Close ();
|
|
|
|
GenWrapper (gen_info);
|
|
|
|
Statistics.CBCount++;
|
|
}
|
|
}
|
|
}
|
|
|