2005-03-23 Mike Kestner <mkestner@novell.com>

* 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.

svn path=/trunk/gtk-sharp/; revision=42168
This commit is contained in:
Mike Kestner 2005-03-23 20:35:15 +00:00
parent 415773f269
commit ac4cc59206
8 changed files with 125 additions and 42 deletions

View file

@ -1,3 +1,17 @@
2005-03-23 Mike Kestner <mkestner@novell.com>
* 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 <mkestner@novell.com>
* gtk/Gtk.metadata : hide TreeSortable.SetSortFunc.

View file

@ -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 \

58
gapi-cdecl-insert Executable file
View file

@ -0,0 +1,58 @@
#!/usr/bin/perl
#
# gapi-cdecl-insert : Inserts il into an assembly for CDecl callback delegates.
#
# Authors: Mike Kestner <mkestner@novell.com>
#
# 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=<file>] <assembly_path>\n" if ($ARGV > 2);
foreach $arg (@ARGV) {
if ($arg =~ /--keyfile=(.*)/) {
$key = $1;
} elsif (-e $arg) {
$assembly = $arg;
} else {
die "Usage: gapi-cdecl-insert [--keyfile=<file>] <assembly_path>\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 = <INFILE>) {
$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=<file>] <dll_path>\n";
}

View file

@ -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);

View file

@ -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

View file

@ -0,0 +1,29 @@
// CDeclCallbackAttribute.cs
//
// Author: Mike Kestner <mkestner@ximian.com>
//
// 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
{
}
}

View file

@ -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;
}
}
}

View file

@ -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: