diff --git a/ChangeLog b/ChangeLog index 11d31cd31..05d85d819 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2005-03-23 Mike Kestner + + * gapi-cdecl-insert : a little perl script to insert modopts + * Makefile.am : dist the new script. + for cdecl callback delegates on win32. + * glade/makefile.win32 : use gapi-cdecl-insert + * glade/XML.custom : add [GLib.CDeclCallback] to RawXMLConnectFunc. + * glib/makefile.win32 : use gapi-cdecl-insert + * glib/CDeclCallbackAttribute.cs : new attr to tag delegates with + that will be invoked from native code. We have to mangle the il + with a modopt otherwise they are stdcall'd. + * glib/ManagedValue.cs : add [GLib.CDeclCallback] to Copy/Free. + switch to using GCHandles instead of the current IntPtr hack. + 2005-03-15 Mike Kestner * gtk/Gtk.metadata : hide TreeSortable.SetSortFunc. diff --git a/Makefile.am b/Makefile.am index aea223aa3..131359949 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,7 @@ SUBDIRS = sources generator parser glib pango atk gdk gtk glade art gnomevfs gno EXTRA_DIST = \ gtk-sharp.snk \ + gapi-cdecl-insert \ makefile.win32 \ AssemblyInfo.cs.in \ ChangeLog \ diff --git a/gapi-cdecl-insert b/gapi-cdecl-insert new file mode 100755 index 000000000..968949da5 --- /dev/null +++ b/gapi-cdecl-insert @@ -0,0 +1,58 @@ +#!/usr/bin/perl +# +# gapi-cdecl-insert : Inserts il into an assembly for CDecl callback delegates. +# +# Authors: Mike Kestner +# +# Copyright (c) 2005 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. + +die "Usage: gapi-cdecl-insert [--keyfile=] \n" if ($ARGV > 2); +foreach $arg (@ARGV) { + if ($arg =~ /--keyfile=(.*)/) { + $key = $1; + } elsif (-e $arg) { + $assembly = $arg; + } else { + die "Usage: gapi-cdecl-insert [--keyfile=] \n"; + } +} + +if ($assembly =~ /(.*)\.dll/) { + $basename = $1; + `ildasm $assembly /out:$basename.raw`; + open(INFILE, $basename . ".raw") || die "Couldn't open $basename.raw\n"; + open(OUTFILE, "> $basename.il") || die "Couldn't open $basename.il\n"; + while ($line = ) { + $insert = 1 if ($line =~ /\.custom instance void .*GLib\.CDeclCallbackAttribute/); + + if ($insert && $line =~ /(.*)\s+(Invoke\(.*)/) { + print OUTFILE "$1 modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) $2"; + $insert = 0; + next; + } + print OUTFILE $line; + } + `ilasm /DLL /QUIET $basename.il`; + `sn -R $assembly gtk-sharp.snk` if ($key); + unlink "$basename.raw"; + unlink "$basename.il"; + unlink "$basename.res"; +} else { + print "This script only works for dlls.\nUsage: gapi-cdecl-insert [--keyfile=] \n"; +} + + diff --git a/glade/XML.custom b/glade/XML.custom index dbfb53196..85767eda7 100644 --- a/glade/XML.custom +++ b/glade/XML.custom @@ -175,6 +175,7 @@ this.handler_type = type; } + [GLib.CDeclCallback] delegate void RawXMLConnectFunc (IntPtr handler_name, IntPtr objekt, IntPtr signal_name, IntPtr signal_data, IntPtr connect_object, int after, IntPtr user_data); diff --git a/glade/makefile.win32 b/glade/makefile.win32 index b5bff4fee..2084ea296 100755 --- a/glade/makefile.win32 +++ b/glade/makefile.win32 @@ -6,6 +6,7 @@ all: windows windows: generated-stamp $(CSC) /unsafe /nowarn:0660,0661 /target:library /r:../glib/glib-sharp.dll /r:../pango/pango-sharp.dll /r:../atk/atk-sharp.dll /r:../gdk/gdk-sharp.dll /r:../gtk/gtk-sharp.dll /out:$(ASSEMBLY) /recurse:*.cs + ../gapi-cdecl-insert --keyfile=gtk-sharp.snk glade-sharp.dll cd glue && make -f makefile.win32 generated-stamp: ../generator/codegen.exe $(APIS) $(I_APIS) *.custom diff --git a/glib/CDeclCallbackAttribute.cs b/glib/CDeclCallbackAttribute.cs new file mode 100644 index 000000000..533dbe427 --- /dev/null +++ b/glib/CDeclCallbackAttribute.cs @@ -0,0 +1,29 @@ +// CDeclCallbackAttribute.cs +// +// Author: Mike Kestner +// +// Copyright (c) 2005 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; + + public sealed class CDeclCallbackAttribute : Attribute + { + } +} diff --git a/glib/ManagedValue.cs b/glib/ManagedValue.cs index 96dce5e39..cb254821b 100644 --- a/glib/ManagedValue.cs +++ b/glib/ManagedValue.cs @@ -25,30 +25,19 @@ namespace GLib { using System.Runtime.InteropServices; using GLib; - // FIXME: - // This used to use GCHandles, but I rewrote it to debug - // some odd interactions. Since the boxed code in GLib is designed - // to not interact directly with the pointers, just using our own - // arbitrary pointer values is fine. Still, it might be useful - // to use GCHandle later on. - internal class ManagedValue { - private class ValueHolder { - public object val; - public int ref_count; - } - private delegate IntPtr CopyFunc (IntPtr ptr); - private delegate void FreeFunc (IntPtr ptr); + [CDeclCallback] + delegate IntPtr CopyFunc (IntPtr gch); + [CDeclCallback] + delegate void FreeFunc (IntPtr gch); - private static Hashtable pointers = new Hashtable (); - private static IntPtr cur_ptr = IntPtr.Zero; - private static CopyFunc copy; - private static FreeFunc free; - private static GType boxed_type = GType.Invalid; + static CopyFunc copy; + static FreeFunc free; + static GType boxed_type = GType.Invalid; [DllImport("libgobject-2.0-0.dll")] - private static extern IntPtr g_boxed_type_register_static (IntPtr typename, CopyFunc copy_func, FreeFunc free_func); + static extern IntPtr g_boxed_type_register_static (IntPtr typename, CopyFunc copy_func, FreeFunc free_func); public static GType GType { get { @@ -65,42 +54,31 @@ namespace GLib { } } - public static IntPtr Copy (IntPtr ptr) + static IntPtr Copy (IntPtr ptr) { - ValueHolder holder = (ValueHolder) pointers[ptr]; - holder.ref_count++; - return ptr; + Console.WriteLine ("Copying ManagedGValue: " + ptr); + GCHandle gch = (GCHandle) ptr; + return (IntPtr) GCHandle.Alloc (gch.Target); } - public static void Free (IntPtr ptr) + static void Free (IntPtr ptr) { - ValueHolder holder = (ValueHolder) pointers[ptr]; - if (holder == null) - return; - holder.ref_count--; - if (holder.ref_count < 1) - pointers.Remove (ptr); + Console.WriteLine ("Freeing ManagedGValue: " + ptr); + GCHandle gch = (GCHandle) ptr; + gch.Free (); } public static IntPtr WrapObject (object obj) { - ValueHolder holder = new ValueHolder (); - holder.val = obj; - holder.ref_count = 1; - cur_ptr = new IntPtr (((int) cur_ptr) + 1); - pointers[cur_ptr] = holder; - return cur_ptr; + Console.WriteLine ("Wrapping Object in ManagedGValue: " + obj); + return (IntPtr) GCHandle.Alloc (obj); } public static object ObjectForWrapper (IntPtr ptr) { - if (!pointers.Contains (ptr)) - return null; - - ValueHolder holder = (ValueHolder) pointers[ptr]; - return holder.val; + Console.WriteLine ("Getting object of ManagedGValue: " + ptr); + return ((GCHandle)ptr).Target; } - } } diff --git a/glib/makefile.win32 b/glib/makefile.win32 index b6914df1d..a2de18845 100644 --- a/glib/makefile.win32 +++ b/glib/makefile.win32 @@ -2,6 +2,7 @@ all: windows windows: $(CSC) /unsafe /nowarn:0660,0661 /target:library /out:glib-sharp.dll /recurse:*.cs + ../gapi-cdecl-insert --keyfile=gtk-sharp.snk glib-sharp.dll cd glue && make -f makefile.win32 clean: