GtkSharp/generator/Method.cs
Gonzalo Paniagua Javier 3821938764 2003-04-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>
* generator/CallbackGen.cs: the new generated wrappers have:
		-(optional) Field of the same type returned by the callback.
		-A call to RemoveIfNotAlive at the beginning. It returns true,
		return the dummy field.
		-Added an object to the ctor signature and pass it to the base
		class.

	* generator/Ctor.cs: added a Params property.

	* generator/Method.cs: set Static property in Parameters if the method
	is static.

	* generator/Parameters.cs: added Static property. The call creation of
	the delegate wrapper (if applicable) uses the new signature. Pass a null
	as object is the method is static.

	* generator/StructBase.cs: set Static for the parameters of the ctors.

	* glib/DelegateWrapper.cs: the ctor takes an object (the one creating
	the wrapper or null) and creates a weak reference to it. Store it in
	a static Hashtable (this way the wrapper itself is not garbage
	collected).
	(RemoveIfNotAlive): called from the native delegate callbacks. If the
	target of the weak reference has been garbage collected, removes itself
	from the hashtable to let the GC dispose this instance and returns true.

	* gdk/Pixbuf.custom:
	* gtk/Clipboard.custom:
	* gtk/GtkSharp.GtkClipboardClearFuncNative.cs:
	* gtk/GtkSharp.GtkClipboardGetFuncNative.cs:
	* glade/XML.custom: changed delegate wrappers to match the new
	signature.

svn path=/trunk/gtk-sharp/; revision=13237
2003-04-06 09:21:15 +00:00

426 lines
11 KiB
C#

// GtkSharp.Generation.Method.cs - The Method Generatable.
//
// Author: Mike Kestner <mkestner@speakeasy.net>
//
// (c) 2001-2002 Mike Kestner
namespace GtkSharp.Generation {
using System;
using System.Collections;
using System.IO;
using System.Xml;
public class Method {
private string libname;
private XmlElement elem;
private Parameters parms;
private ClassBase container_type;
private bool initialized = false;
private string sig, isig, call;
private string rettype, m_ret, s_ret;
private string element_type = null;
private string name, cname, safety;
private string protection = "public";
private bool is_get, is_set;
private bool needs_ref = false;
public Method (string libname, XmlElement elem, ClassBase container_type)
{
this.elem = elem;
if (elem["parameters"] != null)
parms = new Parameters (elem["parameters"]);
this.container_type = container_type;
this.name = elem.GetAttribute("name");
if (name == "GetType")
name = "GetGType";
// override library - used in pixbuf API fixage
if (elem.HasAttribute ("library"))
this.libname = elem.GetAttribute ("library");
else
this.libname = libname;
// caller does not own reference?
if (elem.HasAttribute ("needs_ref"))
this.needs_ref = (elem.GetAttribute ("needs_ref") == "1");
}
public bool IsGetter {
get {
return is_get;
}
}
public bool IsSetter {
get {
return is_set;
}
}
public string Name {
get {
return name;
}
set {
name = value;
}
}
public Parameters Params {
get {
return parms;
}
}
public string Protection {
get {
return protection;
}
set {
protection = value;
}
}
public string ReturnType {
get {
return s_ret;
}
}
public override bool Equals (object o)
{
if (!(o is Method))
return false;
/*
return (this == (Method) o);
}
public static bool operator == (Method a, Method b)
{
if (a == null)
return (b
*/
Method a = this;
Method b = (Method) o;
if (a.Name != b.Name)
return false;
if (a.Params == null)
return b.Params == null;
if (b.Params == null)
return false;
return (a.Params.SignatureTypes == b.Params.SignatureTypes);
}
/*
public static bool operator != (Method a, Method b)
{
return !(
if (a.Name == b.Name)
return false;
if (a.Params == null)
return b.Params != null;
if (b.Params == null)
return true;
return (a.Params.SignatureTypes != b.Params.SignatureTypes);
}
*/
private bool Initialize ()
{
if (initialized)
return true;
if (parms != null && !parms.Validate ()) {
Console.Write ("in method " + Name + " ");
return false;
}
XmlElement ret_elem = elem["return-type"];
if (ret_elem == null) {
Console.Write("Missing return type in method ");
Statistics.ThrottledCount++;
return false;
}
rettype = ret_elem.GetAttribute("type");
m_ret = SymbolTable.GetMarshalReturnType(rettype);
s_ret = SymbolTable.GetCSType(rettype);
cname = elem.GetAttribute("cname");
if (ret_elem.HasAttribute("element_type"))
element_type = ret_elem.GetAttribute("element_type");
bool is_shared = elem.HasAttribute("shared");
if (ret_elem.HasAttribute("array")) {
s_ret += "[]";
m_ret += "[]";
}
if (parms != null && parms.ThrowsException)
safety = "unsafe ";
else
safety = "";
is_get = ((parms != null && ((parms.IsAccessor && s_ret == "void") || (parms.Count == 0 && s_ret != "void")) || (parms == null && s_ret != "void")) && Name.Length > 3 && Name.Substring(0, 3) == "Get");
is_set = ((parms != null && (parms.IsAccessor || (parms.Count == 1 && s_ret == "void"))) && (Name.Length > 3 && Name.Substring(0, 3) == "Set"));
if (parms != null) {
parms.Static = is_shared;
parms.CreateSignature (is_set);
sig = "(" + parms.Signature + ")";
isig = "(" + (is_shared ? "" : container_type.MarshalType + " raw, ") + parms.ImportSig + ");";
call = "(" + (is_shared ? "" : container_type.CallByName () + ", ") + parms.CallString + ")";
} else {
sig = "()";
isig = "(" + (is_shared ? "" : container_type.MarshalType + " raw") + ");";
call = "(" + (is_shared ? "" : container_type.CallByName ()) + ")";
}
initialized = true;
return true;
}
public bool Validate ()
{
if (!Initialize ())
return false;
if (m_ret == "" || s_ret == "") {
Console.Write("rettype: " + rettype + " method ");
Statistics.ThrottledCount++;
return false;
}
return true;
}
private Method GetComplement ()
{
char complement;
if (is_get)
complement = 'S';
else
complement = 'G';
return container_type.GetMethod (complement + elem.GetAttribute("name").Substring (1));
}
private void GenerateDeclCommon (StreamWriter sw, ClassBase implementor)
{
if (elem.HasAttribute("shared"))
sw.Write("static ");
sw.Write(safety);
Method dup = null;
if (Name == "ToString")
sw.Write("override ");
else if (Name == "GetGType" && container_type is ObjectGen)
sw.Write("new ");
else if (elem.HasAttribute("new_flag") || (container_type != null && (dup = container_type.GetMethodRecursively (Name)) != null) || (implementor != null && (dup = implementor.GetMethodRecursively (Name)) != null)) {
if (dup != null && dup.parms != null)
dup.parms.CreateSignature (false);
if (dup != null && ((dup.parms != null && dup.parms.Signature == parms.Signature) || (dup.parms == null && parms == null)))
sw.Write("new ");
}
if (is_get || is_set) {
if (s_ret == "void")
s_ret = parms.AccessorReturnType;
sw.Write(s_ret);
sw.Write(" ");
sw.Write(Name.Substring (3));
sw.WriteLine(" { ");
} else {
sw.Write(s_ret + " " + Name + sig);
}
}
public void GenerateDecl (StreamWriter sw)
{
if (!Initialize ())
return;
if (elem.HasAttribute("shared"))
return;
GenerateComments (sw);
if (is_get || is_set)
{
Method comp = GetComplement ();
if (comp != null && comp.Validate () && is_set)
return;
sw.Write("\t\t");
GenerateDeclCommon (sw, null);
sw.Write("\t\t\t");
sw.Write ((is_get) ? "get;" : "set;");
if (comp != null && comp.is_set)
sw.WriteLine (" set;");
else
sw.WriteLine ();
sw.WriteLine ("\t\t}");
}
else
{
sw.Write("\t\t");
GenerateDeclCommon (sw, null);
sw.WriteLine (";");
}
Statistics.MethodCount++;
}
void GenerateComments (StreamWriter sw)
{
string summary, sname;
sw.WriteLine();
if (is_get || is_set) {
summary = "Property";
sname = Name.Substring (3);
} else {
summary = "Method";
sname = Name;
}
sw.WriteLine("\t\t/// <summary> " + sname + " " + summary + " </summary>");
sw.WriteLine("\t\t/// <remarks> To be completed </remarks>");
}
public void GenerateImport (StreamWriter sw)
{
sw.WriteLine("\t\t[DllImport(\"" + libname + "\")]");
sw.Write("\t\tstatic extern " + safety + m_ret + " " + cname + isig);
sw.WriteLine();
}
public void Generate (StreamWriter sw, ClassBase implementor)
{
Generate (sw, implementor, true);
}
public void Generate (StreamWriter sw, ClassBase implementor, bool gen_docs)
{
Method comp = null;
if (!Initialize ())
return;
if (implementor != null && elem.HasAttribute("shared"))
return;
/* we are generated by the get Method, if there is one */
if (is_set || is_get)
{
if (container_type.GetPropertyRecursively (Name.Substring (3)) != null)
return;
comp = GetComplement ();
if (comp != null && comp.Validate () && is_set && parms.AccessorReturnType == comp.s_ret)
return;
if (comp != null && is_set && parms.AccessorReturnType != comp.s_ret)
{
is_set = false;
parms.CreateSignature (false);
call = "(Handle, " + parms.CallString + ")";
comp = null;
}
/* some setters take more than one arg */
if (comp != null && !comp.is_set)
comp = null;
}
GenerateImport (sw);
if (comp != null && s_ret == comp.parms.AccessorReturnType)
comp.GenerateImport (sw);
if (gen_docs)
GenerateComments (sw);
sw.Write("\t\t");
if (protection != "")
sw.Write("{0} ", protection);
GenerateDeclCommon (sw, implementor);
if (is_get || is_set)
{
sw.Write ("\t\t\t");
sw.Write ((is_get) ? "get" : "set");
GenerateBody (sw, "\t");
}
else
GenerateBody (sw, "");
if (is_get || is_set)
{
if (comp != null && s_ret == comp.parms.AccessorReturnType)
{
sw.WriteLine ();
sw.Write ("\t\t\tset");
comp.GenerateBody (sw, "\t");
}
sw.WriteLine ();
sw.WriteLine ("\t\t}");
}
else
sw.WriteLine();
sw.WriteLine();
Statistics.MethodCount++;
}
public void GenerateBody (StreamWriter sw, string indent)
{
GenerateBody(sw, indent, "");
}
public void GenerateBody (StreamWriter sw, string indent, string cast_type)
{
sw.WriteLine(" {");
if (parms != null)
parms.Initialize(sw, is_get, is_set, indent);
sw.Write(indent + "\t\t\t");
if (m_ret == "void") {
sw.WriteLine(cname + call + ";");
} else {
if (SymbolTable.IsObject (rettype) || SymbolTable.IsOpaque (rettype))
{
sw.WriteLine(m_ret + " raw_ret = " + cname + call + ";");
sw.WriteLine(indent +"\t\t\t" + s_ret + " ret = " + SymbolTable.FromNativeReturn(rettype, "raw_ret") + ";");
if (needs_ref)
sw.WriteLine(indent + "\t\t\tret.Ref ();");
if (SymbolTable.IsOpaque (rettype))
sw.WriteLine(indent + "\t\t\tif (ret == null) ret = new " + s_ret + "(raw_ret);");
}
else {
sw.WriteLine(m_ret + " raw_ret = " + cname + call + ";");
sw.Write(indent + "\t\t\t");
string raw_parms = "raw_ret";
if (element_type != null)
raw_parms += ", typeof (" + element_type + ")";
sw.WriteLine(s_ret + " ret = " + SymbolTable.FromNativeReturn(rettype, raw_parms) + ";");
}
}
if (parms != null) {
parms.Finish (sw, indent);
parms.HandleException (sw, indent);
}
if (is_get && parms != null)
sw.WriteLine (indent + "\t\t\treturn " + parms.AccessorName + ";");
else if (m_ret != "void")
sw.WriteLine (indent + "\t\t\treturn ret;");
sw.Write(indent + "\t\t}");
}
}
}