2007-09-11 Mike Kestner <mkestner@novell.com>

* gtk/Gtk.metadata: virtual_method rules for GInterface generation.
	* generator/ReturnValue.cs (ToNative): new method for the virtual
	method generation.
	* generator/Parameters.cs (FromNative): null guarding.
	* generator/ManagedCallString.cs: rework for interface method
	generation including callback and error param support.
	* generator/CallbackGen.cs: Invoker support. new class that deals
	with persistence of native and wrapper delegates in native to managed
	callback method signatures.
	* generator/VirtualMethod.cs: support for generation of interface
	methods, and all the funky parameters that come with that.
	* generator/InterfaceGen.cs: Fill out the adapter implementation.
	* generator/MethodBody.cs: Initialize overload. Extend ThrowsException
	to support GError outside the last parameter slot.
	* glib/GInterfaceAttribute.cs: New attribute to mark interfaces and
	obtain adapter type.
	* glib/Object.cs (AddInterfaces): interface registration method.
	* glib/GInterfaceAdapter.cs: New abstract class for interface
	adapter generation.
	* glib/Makefile.am: add new files.

svn path=/trunk/gtk-sharp/; revision=85658
This commit is contained in:
Mike Kestner 2007-09-11 20:34:24 +00:00
parent bf1bec4f41
commit c93ecb7f88
13 changed files with 435 additions and 69 deletions

View File

@ -1,3 +1,26 @@
2007-09-11 Mike Kestner <mkestner@novell.com>
* gtk/Gtk.metadata: virtual_method rules for GInterface generation.
* generator/ReturnValue.cs (ToNative): new method for the virtual
method generation.
* generator/Parameters.cs (FromNative): null guarding.
* generator/ManagedCallString.cs: rework for interface method
generation including callback and error param support.
* generator/CallbackGen.cs: Invoker support. new class that deals
with persistence of native and wrapper delegates in native to managed
callback method signatures.
* generator/VirtualMethod.cs: support for generation of interface
methods, and all the funky parameters that come with that.
* generator/InterfaceGen.cs: Fill out the adapter implementation.
* generator/MethodBody.cs: Initialize overload. Extend ThrowsException
to support GError outside the last parameter slot.
* glib/GInterfaceAttribute.cs: New attribute to mark interfaces and
obtain adapter type.
* glib/Object.cs (AddInterfaces): interface registration method.
* glib/GInterfaceAdapter.cs: New abstract class for interface
adapter generation.
* glib/Makefile.am: add new files.
2007-09-11 Mike Kestner <mkestner@novell.com>
* gtk/Object.custom (Destroy): add a null check to avoid

View File

@ -60,6 +60,14 @@ namespace GtkSharp.Generation {
return true;
}
public string InvokerName {
get {
if (!valid)
return String.Empty;
return NS + "Sharp." + Name + "Invoker";
}
}
public override string MarshalType {
get {
if (valid)
@ -86,6 +94,72 @@ namespace GtkSharp.Generation {
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] = "IntPtr.Zero";
}
return String.Join (", ", result);
}
}
MethodBody body;
void GenInvoker (GenerationInfo gen_info, StreamWriter sw)
{
sw.WriteLine ("\tinternal class " + Name + "Invoker {");
sw.WriteLine ();
sw.WriteLine ("\t\t" + Name + "Native native_cb;");
sw.WriteLine ();
sw.WriteLine ("\t\tinternal " + Name + "Invoker (" + Name + "Native native_cb)");
sw.WriteLine ("\t\t{");
sw.WriteLine ("\t\t\tthis.native_cb = native_cb;");
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";
@ -94,7 +168,10 @@ namespace GtkSharp.Generation {
if (!Validate ())
return String.Empty;
StreamWriter sw = gen_info.OpenStream (qualname);
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 ();
@ -105,6 +182,7 @@ namespace GtkSharp.Generation {
sw.WriteLine ("\t[GLib.CDeclCallback]");
sw.WriteLine ("\tinternal delegate " + retval.MarshalType + " " + wrapper + "(" + parms.ImportSignature + ");");
sw.WriteLine ();
GenInvoker (gen_info, sw);
sw.WriteLine ("\tinternal class " + Name + "Wrapper {");
sw.WriteLine ();
sw.WriteLine ("\t\tpublic " + retval.MarshalType + " NativeCallback (" + parms.ImportSignature + ")");
@ -214,6 +292,7 @@ namespace GtkSharp.Generation {
sw.WriteLine ("#endregion");
sw.WriteLine ("}");
sw.Close ();
gen_info.Writer = save_sw;
return NS + "Sharp." + Name + "Wrapper";
}

View File

@ -81,14 +81,15 @@ namespace GtkSharp.Generation {
return;
foreach (VirtualMethod vm in vms) {
sw.WriteLine ("\t\t" + vm.NativeDelegate);
if (vm.IsValid)
sw.WriteLine ("\t\t" + vm.NativeDelegate);
}
sw.WriteLine ();
}
void GenerateIfaceStruct (StreamWriter sw)
{
sw.WriteLine ("\t\t" + IfaceName + " iface;");
sw.WriteLine ("\t\tstatic " + IfaceName + " iface;");
sw.WriteLine ();
sw.WriteLine ("\t\tstruct " + IfaceName + " {");
sw.WriteLine ("\t\t\tpublic IntPtr gtype;");
@ -100,7 +101,11 @@ namespace GtkSharp.Generation {
sw.WriteLine ("\t\t\tpublic IntPtr " + member + ";");
else if (member is VirtualMethod) {
VirtualMethod vm = member as VirtualMethod;
sw.WriteLine ("\t\t\tpublic " + vm.Name + "Delegate " + vm.CName + ";");
bool has_method = methods [vm.Name] != null;
if (!has_method)
Console.WriteLine ("Interface " + QualifiedName + " virtual method " + vm.Name + " has no matching method to invoke.");
string type = has_method && vm.IsValid ? vm.Name + "Delegate" : "IntPtr";
sw.WriteLine ("\t\t\tpublic " + type + " " + vm.CName + ";");
}
}
@ -108,49 +113,64 @@ namespace GtkSharp.Generation {
sw.WriteLine ();
}
void GenerateCtor (StreamWriter sw)
void GenerateStaticCtor (StreamWriter sw)
{
sw.WriteLine ("\t\tprivate " + Name + "Adapter ()");
sw.WriteLine ("\t\tstatic " + Name + "Adapter ()");
sw.WriteLine ("\t\t{");
foreach (VirtualMethod vm in vms)
sw.WriteLine ("\t\t\tiface.{0} = new {1}Delegate ({1}Callback);", vm.CName, vm.Name);
sw.WriteLine ("\t\t}");
sw.WriteLine ();
}
void GenerateAdapterProp (StreamWriter sw)
{
sw.WriteLine ("\t\tstatic " + Name + "Adapter singleton;");
sw.WriteLine ();
sw.WriteLine ("\t\tinternal " + Name + "Adapter Adapter {");
sw.WriteLine ("\t\t\tget {");
sw.WriteLine ("\t\t\t\tif (singleton == null)");
sw.WriteLine ("\t\t\t\t\tsingleton = new " + Name + "Adapter ();");
sw.WriteLine ("\t\t\t\treturn singleton;");
sw.WriteLine ("\t\t\t}");
foreach (VirtualMethod vm in vms) {
bool has_method = methods [vm.Name] != null;
if (has_method && vm.IsValid)
sw.WriteLine ("\t\t\tiface.{0} = new {1}Delegate ({1}Callback);", vm.CName, vm.Name);
}
sw.WriteLine ("\t\t}");
sw.WriteLine ();
}
void GenerateInitialize (StreamWriter sw)
{
sw.WriteLine ("\t\tpublic void Initialize (IntPtr ifaceptr, IntPtr data)");
sw.WriteLine ("\t\tstatic void Initialize (IntPtr ifaceptr, IntPtr data)");
sw.WriteLine ("\t\t{");
sw.WriteLine ("\t\t\t" + IfaceName + " iface = (" + IfaceName + ") Marshal.PtrToStructure (ifaceptr, typeof (" + IfaceName + "));");
sw.WriteLine ("\t\t\t" + IfaceName + " native_iface = (" + IfaceName + ") Marshal.PtrToStructure (ifaceptr, typeof (" + IfaceName + "));");
foreach (VirtualMethod vm in vms)
sw.WriteLine ("\t\t\tiface." + vm.CName + " = this.iface." + vm.CName + ";");
sw.WriteLine ("\t\t\tMarshal.StructureToPtr (iface, ifaceptr, false);");
sw.WriteLine ("\t\t\tnative_iface." + vm.CName + " = iface." + vm.CName + ";");
sw.WriteLine ("\t\t\tMarshal.StructureToPtr (native_iface, ifaceptr, false);");
sw.WriteLine ("\t\t\tGCHandle gch = (GCHandle) data;");
sw.WriteLine ("\t\t\tgch.Free ();");
sw.WriteLine ("\t\t}");
sw.WriteLine ();
}
void GenerateCallbacks (StreamWriter sw)
{
foreach (VirtualMethod vm in vms) {
if (methods [vm.Name] == null)
continue;
sw.WriteLine ();
vm.GenerateCallback (sw);
}
}
void GenerateCtor (StreamWriter sw)
{
sw.WriteLine ("\t\tpublic " + Name + "Adapter ()");
sw.WriteLine ("\t\t{");
sw.WriteLine ("\t\t\tInitHandler = new GLib.GInterfaceInitHandler (Initialize);");
sw.WriteLine ("\t\t}");
sw.WriteLine ();
}
void GenerateGType (StreamWriter sw)
{
Method m = GetMethod ("GetType");
m.GenerateImport (sw);
sw.WriteLine ("\t\tpublic override GLib.GType GType {");
sw.WriteLine ("\t\t\tget {");
sw.WriteLine ("\t\t\t\treturn new GLib.GType (" + m.CName + " ());");
sw.WriteLine ("\t\t\t}");
sw.WriteLine ("\t\t}");
sw.WriteLine ();
}
void GenerateAdapter (GenerationInfo gen_info)
{
StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name + "Adapter");
@ -166,10 +186,11 @@ namespace GtkSharp.Generation {
GenerateDelegates (sw);
GenerateIfaceStruct (sw);
GenerateCtor (sw);
GenerateAdapterProp (sw);
GenerateInitialize (sw);
GenerateStaticCtor (sw);
GenerateCallbacks (sw);
GenerateInitialize (sw);
GenerateCtor (sw);
GenerateGType (sw);
sw.WriteLine ("\t}");
sw.WriteLine ("#endregion");
@ -253,11 +274,12 @@ namespace GtkSharp.Generation {
Statistics.IFaceCount++;
}
#if false
public void GenerateNotQuiteReadyYet (GenerationInfo gen_info)
{
ArrayList tmp = new ArrayList ();
foreach (VirtualMethod vm in vms) {
if (vm.Validate())
if (vm.IsValid)
tmp.Add (vm);
else {
members.Remove (vm);
@ -268,9 +290,11 @@ namespace GtkSharp.Generation {
GenerateAdapter (gen_info);
GenerateInterface (gen_info);
}
#endif
public override void Generate (GenerationInfo gen_info)
{
GenerateAdapter (gen_info);
StreamWriter sw = gen_info.Writer = gen_info.OpenStream (Name);
sw.WriteLine ("namespace " + NS + " {");
@ -278,6 +302,7 @@ namespace GtkSharp.Generation {
sw.WriteLine ("\tusing System;");
sw.WriteLine ();
sw.WriteLine ("#region Autogenerated code");
sw.WriteLine ("\t[GLib.GInterface (typeof (" + Name + "Adapter))]");
sw.WriteLine ("\tpublic interface " + Name + " : GLib.IWrapper {");
sw.WriteLine ();

View File

@ -29,18 +29,26 @@ namespace GtkSharp.Generation {
ArrayList parms = new ArrayList ();
ArrayList special = new ArrayList ();
bool has_error;
public ManagedCallString (Parameters parms)
{
for (int i = 1; i < parms.Count; i ++) {
Parameter p = parms [i];
if (p.IsLength && parms [i-1].IsString)
if (p.IsLength && parms [i-1].IsString)
continue;
else if (p.Scope == "notified")
i += 2;
else if (p is ErrorParameter) {
has_error = true;
continue;
}
this.parms.Add (p);
IGeneratable igen = p.Generatable;
if ((igen is StructGen || p.PassAs != "") &&
(p.Name != p.FromNative (p.Name)))
if (p.PassAs != String.Empty && (p.Name != p.FromNative (p.Name)))
this.special.Add (true);
else if (p.Generatable is CallbackGen)
this.special.Add (true);
else
this.special.Add (false);
@ -51,6 +59,9 @@ namespace GtkSharp.Generation {
{
string ret = "";
if (has_error)
ret = indent + "error = IntPtr.Zero;\n";
for (int i = 0; i < parms.Count; i ++) {
if ((bool)special[i] == false)
continue;
@ -58,10 +69,14 @@ namespace GtkSharp.Generation {
Parameter p = parms [i] as Parameter;
IGeneratable igen = p.Generatable;
ret += indent + igen.QualifiedName + " my" + p.Name;
if (igen is StructGen || p.PassAs == "ref")
ret += " = " + p.FromNative (p.Name);
ret += ";\n";
if (igen is CallbackGen) {
ret += indent + String.Format ("{0} {1}_invoker = new {0} ({1});\n", (igen as CallbackGen).InvokerName, p.Name);
} else {
ret += indent + igen.QualifiedName + " my" + p.Name;
if (p.PassAs == "ref")
ret += " = " + p.FromNative (p.Name);
ret += ";\n";
}
}
return ret;
@ -77,7 +92,10 @@ namespace GtkSharp.Generation {
for (int i = 0; i < parms.Count; i ++) {
Parameter p = parms [i] as Parameter;
result [i] = p.PassAs == "" ? "" : p.PassAs + " ";
result [i] += ((bool)special[i]) ? "my" + p.Name : p.FromNative (p.Name);
if (p.Generatable is CallbackGen)
result [i] += p.Name + "_invoker.Handler";
else
result [i] += ((bool)special[i]) ? "my" + p.Name : p.FromNative (p.Name);
}
return String.Join (", ", result);
@ -94,7 +112,9 @@ namespace GtkSharp.Generation {
Parameter p = parms [i] as Parameter;
IGeneratable igen = p.Generatable;
if (igen is StructBase)
if (igen is CallbackGen)
continue;
else if (igen is StructBase || igen is ByRefGen)
ret += indent + String.Format ("if ({0} != IntPtr.Zero) System.Runtime.InteropServices.Marshal.StructureToPtr (my{0}, {0}, false);\n", p.Name);
else
ret += indent + p.Name + " = " + igen.ToNativeReturn ("my" + p.Name) + ";\n";

View File

@ -75,6 +75,11 @@ namespace GtkSharp.Generation {
return String.Join (", ", result);
}
public void Initialize (GenerationInfo gen_info)
{
Initialize (gen_info, false, false, String.Empty);
}
public void Initialize (GenerationInfo gen_info, bool is_get, bool is_set, string indent)
{
if (parameters.Count == 0)
@ -124,7 +129,6 @@ namespace GtkSharp.Generation {
sw.WriteLine (indent + "\t\t\t{0} {1}_wrapper = new {0} ({1});", wrapper, name);
break;
}
}
}
@ -158,10 +162,17 @@ namespace GtkSharp.Generation {
public bool ThrowsException {
get {
if (parameters.Count < 1)
return false;
int idx = parameters.Count - 1;
return parameters [parameters.Count - 1].CType == "GError**";
while (idx >= 0) {
if (parameters [idx].IsUserData)
idx--;
else if (parameters [idx].CType == "GError**")
return true;
else
break;
}
return false;
}
}
}

View File

@ -285,7 +285,9 @@ namespace GtkSharp.Generation {
public string FromNative (string var)
{
if (Generatable is HandleBase)
if (Generatable == null)
return String.Empty;
else if (Generatable is HandleBase)
return ((HandleBase)Generatable).FromNative (var, Owned);
else
return Generatable.FromNative (var);

View File

@ -137,6 +137,22 @@ namespace GtkSharp.Generation {
return IGen.FromNativeReturn (var);
}
public string ToNative (string var)
{
if (IGen == null)
return String.Empty;
if (ElementType.Length > 0) {
string args = ", typeof (" + ElementType + "), " + (Owned ? "true" : "false") + ", " + (ElementsOwned ? "true" : "false");
var = "new " + IGen.QualifiedName + "(" + var + args + ")";
}
if (IGen is IManualMarshaler)
return (IGen as IManualMarshaler).AllocNative (var);
else
return IGen.ToNativeReturn (var);
}
public bool Validate ()
{
if (MarshalType == "" || CSType == "") {

View File

@ -53,6 +53,24 @@ namespace GtkSharp.Generation {
}
}
bool IsGetter {
get {
return (Name.StartsWith ("Get") || Name.StartsWith ("Has")) && ((!retval.IsVoid && parms.Count == 1) || (retval.IsVoid && parms.Count == 2 && parms [1].PassAs == "out"));
}
}
bool IsSetter {
get {
if (!Name.StartsWith ("Set") || !retval.IsVoid)
return false;
if (parms.Count == 2 || (parms.Count == 4 && parms [1].Scope == "notified"))
return true;
else
return false;
}
}
public string MarshalReturnType {
get {
return SymbolTable.Table.GetToNativeReturnType (elem["return-type"].GetAttribute("type"));
@ -73,39 +91,64 @@ namespace GtkSharp.Generation {
public void GenerateCallback (StreamWriter sw)
{
if (!Validate ())
return;
ManagedCallString call = new ManagedCallString (parms);
string type = parms [0].CSType;
string name = parms [0].Name;
string call_string = "__obj." + Name + " (" + call + ")";
if (IsGetter)
call_string = "__obj." + (Name.StartsWith ("Get") ? Name.Substring (3) : Name);
else if (IsSetter)
call_string = "__obj." + Name.Substring (3) + " = " + call;
sw.WriteLine ("\t\tstatic " + MarshalReturnType + " " + Name + "Callback (" + parms.ImportSignature + ")");
sw.WriteLine ("\t\t{");
sw.WriteLine ("\t\t\t" + type + " __obj = GLib.Object.GetObject (" + name + ", false) as " + type + ";");
sw.Write (call.Setup ("\t\t\t"));
if (retval.CSType == "void")
sw.WriteLine ("\t\t\t" + call_string + ";");
else {
sw.WriteLine ("\t\t\treturn " + SymbolTable.Table.ToNativeReturn (retval.CType, call_string) + ";");
}
if (retval.IsVoid) {
if (IsGetter) {
Parameter p = parms [1];
string out_name = p.Name;
if (p.MarshalType != p.CSType)
out_name = "my" + out_name;
sw.WriteLine ("\t\t\t" + out_name + " = " + call_string + ";");
} else
sw.WriteLine ("\t\t\t" + call_string + ";");
} else
sw.WriteLine ("\t\t\t" + retval.ToNativeType + " result = " + retval.ToNative (call_string) + ";");
sw.Write (call.Finish ("\t\t\t"));
if (!retval.IsVoid)
sw.WriteLine ("\t\t\treturn result;");
sw.WriteLine ("\t\t}");
}
public bool Validate ()
enum ValidState {
Unvalidated,
Invalid,
Valid
}
ValidState vstate = ValidState.Unvalidated;
public bool IsValid {
get {
if (vstate == ValidState.Unvalidated)
return Validate ();
else
return vstate == ValidState.Valid;
}
}
bool Validate ()
{
if (!parms.Validate () || !retval.Validate ()) {
Console.Write ("in virtual method " + Name + " ");
vstate = ValidState.Invalid;
return false;
}
for (int i = 0; i < parms.Count; i++) {
Parameter p = parms [i];
if (p.Generatable is CallbackGen) {
Console.Write("Callback: " + p.CSType + " in virtual method " + Name + " ");
Statistics.ThrottledCount++;
return false;
}
}
vstate = ValidState.Valid;
return true;
}
}

67
glib/GInterfaceAdapter.cs Normal file
View File

@ -0,0 +1,67 @@
// GInterfaceAdapter.cs
//
// Author: Mike Kestner <mkestner@novell.com>
//
// 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 Lesser 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser 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 GLib {
using System;
using System.Runtime.InteropServices;
public delegate void GInterfaceInitHandler (IntPtr iface_ptr, IntPtr data);
internal delegate void GInterfaceFinalizeHandler (IntPtr iface_ptr, IntPtr data);
internal struct GInterfaceInfo {
internal GInterfaceInitHandler InitHandler;
internal GInterfaceFinalizeHandler FinalizeHandler;
internal IntPtr Data;
}
public abstract class GInterfaceAdapter {
GInterfaceInfo info;
protected GInterfaceAdapter ()
{
info.FinalizeHandler = new GInterfaceFinalizeHandler (Finalize);
info.Data = (IntPtr) GCHandle.Alloc (this);
}
protected GInterfaceInitHandler InitHandler {
set {
info.InitHandler = value;
}
}
public abstract GType GType { get; }
internal GInterfaceInfo Info {
get {
return info;
}
}
void Finalize (IntPtr iface_ptr, IntPtr data)
{
GCHandle gch = (GCHandle) data;
gch.Free ();
}
}
}

View File

@ -0,0 +1,42 @@
// GInterfaceAttribute.cs
//
// 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 Lesser 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser 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 GLib {
using System;
[AttributeUsage (AttributeTargets.Interface)]
public sealed class GInterfaceAttribute : Attribute {
Type adapter_type;
public GInterfaceAttribute (Type adapter_type)
{
this.adapter_type = adapter_type;
}
public Type AdapterType {
get {
return adapter_type;
}
set {
adapter_type = value;
}
}
}
}

View File

@ -28,6 +28,8 @@ sources = \
ExceptionManager.cs \
FileUtils.cs \
GException.cs \
GInterfaceAdapter.cs \
GInterfaceAttribute.cs \
GString.cs \
GType.cs \
GTypeAttribute.cs \

View File

@ -183,6 +183,24 @@ namespace GLib {
}
}
[DllImport("libgobject-2.0-0.dll")]
static extern void g_type_add_interface_static (IntPtr gtype, IntPtr iface_type, ref GInterfaceInfo info);
static void AddInterfaces (GType gtype, Type t)
{
foreach (Type iface in t.GetInterfaces ()) {
if (!iface.IsDefined (typeof (GInterfaceAttribute), true) || iface.IsAssignableFrom (t.BaseType))
continue;
GInterfaceAttribute attr = iface.GetCustomAttributes (typeof (GInterfaceAttribute), false) [0] as GInterfaceAttribute;
GInterfaceAdapter adapter = Activator.CreateInstance (attr.AdapterType, null) as GInterfaceAdapter;
GInterfaceInfo info = adapter.Info;
g_type_add_interface_static (gtype.Val, adapter.GType.Val, ref info);
Console.WriteLine (adapter);
}
}
[DllImport("glibsharpglue-2")]
static extern IntPtr gtksharp_register_type (IntPtr name, IntPtr parent_type);
@ -221,6 +239,7 @@ namespace GLib {
GLib.GType.Register (gtype, t);
ConnectDefaultHandlers (gtype, t);
InvokeClassInitializers (gtype, t);
AddInterfaces (gtype, t);
g_types[t] = gtype;
return gtype;
}

View File

@ -128,6 +128,10 @@
<attr path="/api/namespace/interface[@cname='GtkEditable']/signal[@name='DeleteText']" name="name">TextDeleted</attr>
<attr path="/api/namespace/interface[@cname='GtkEditable']/signal[@name='InsertText']/*/*[@name='position']" name="pass_as">ref</attr>
<attr path="/api/namespace/interface[@cname='GtkEditable']/signal[@name='InsertText']" name="name">TextInserted</attr>
<attr path="/api/namespace/interface[@cname='GtkEditable']/virtual_method[@name='DoDeleteText']" name="name">DeleteText</attr>
<attr path="/api/namespace/interface[@cname='GtkEditable']/virtual_method[@name='DoInsertText']" name="name">InsertText</attr>
<attr path="/api/namespace/interface[@cname='GtkEditable']/virtual_method[@cname='do_insert_text']/*/*[@name='position']" name="pass_as">ref</attr>
<attr path="/api/namespace/interface[@cname='GtkEditable']/virtual_method[@name='SetSelectionBounds']" name="name">SelectRegion</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/property[@name='Action']" name="new_flag">1</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/method[@name='GetCurrentFolder']/return-type" name="type">gfilename*</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/method[@name='GetFilename']/return-type" name="type">gfilename*</attr>
@ -146,17 +150,30 @@
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/method[@cname='gtk_file_chooser_list_shortcut_folder_uris']/return-type" name="element_type">gchar*</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/method[@cname='gtk_file_chooser_list_shortcut_folder_uris']/return-type" name="elements_owned">true</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/method[@cname='gtk_file_chooser_list_shortcut_folder_uris']/return-type" name="owned">true</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@name='GetPaths']" name="name">GetFilenames</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@cname='get_paths']/return-type" name="element_type">gfilename*</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@cname='get_paths']/return-type" name="elements_owned">true</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@cname='get_paths']/return-type" name="owned">true</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@name='ListFilters']" name="name">GetFilters</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@cname='list_filters']/return-type" name="element_type">gchar*</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@cname='list_filters']/return-type" name="elements_owned">true</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@cname='list_filters']/return-type" name="owned">true</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@name='ListShortcutFolders']" name="name">GetShortcutFolders</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@cname='list_shortcut_folders']/return-type" name="element_type">gchar*</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@cname='list_shortcut_folders']/return-type" name="elements_owned">true</attr>
<attr path="/api/namespace/interface[@cname='GtkFileChooser']/virtual_method[@cname='list_shortcut_folders']/return-type" name="owned">true</attr>
<attr path="/api/namespace/interface[@cname='GtkRecentChooser']/virtual_method[@name='GetRecentManager']" name="hidden">1</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='Foreach']/*/*[@name='func']" name="scope">call</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetIterFirst']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/*[@name='GetIterFirst']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='Get']" name="hidden">1</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetIterFromString']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetIter']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetPath']/return-type" name="owned">true</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='GetValue']/*/*[@name='value']" name="pass_as">ref</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterChildren']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterNext']/*/*[@name='iter']" name="pass_as">ref</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterNthChild']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='IterParent']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/*[@name='GetIterFromString']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/*[@name='GetIter']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/*[@name='GetPath']/return-type" name="owned">true</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/*[@name='GetValue']/*/*[@name='value']" name="pass_as">ref</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/*[@name='IterChildren']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/*[@name='IterNext']/*/*[@name='iter']" name="pass_as">ref</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/*[@name='IterNthChild']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/*[@name='IterParent']/*/*[@name='iter']" name="pass_as">out</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowChanged']" name="name">EmitRowChanged</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowDeleted']" name="name">EmitRowDeleted</attr>
<attr path="/api/namespace/interface[@cname='GtkTreeModel']/method[@name='RowHasChildToggled']" name="name">EmitRowHasChildToggled</attr>