* generator/OpaqueGen.cs (Generate): Tweak the generated Ref/Unref
a bit; only Ref the pointer if Owned is false (and then set it to true), and vice versa for Unref. * glib/Opaque.cs (Opaque): set owned before setting Raw, so that Raw will be reffed properly. (GetOpaque): Fix this up to dtrt in all cases with refcounted opaques. * gtk/TreeView.custom (GetPathAtPos): Use "GetOpaque(...)" rather than "new TreePath()" * sample/opaquetest/*: regression test for opaque free/ref/unref handling * sample/Makefile.am (SUBDIRS): add opaquetest * configure.in.in (AC_OUTPUT): add opaquetest files svn path=/trunk/gtk-sharp/; revision=48168
This commit is contained in:
parent
c254638a5a
commit
12cd8d0d17
15 changed files with 794 additions and 14 deletions
21
ChangeLog
21
ChangeLog
|
@ -1,3 +1,24 @@
|
|||
2005-08-09 Dan Winship <danw@novell.com>
|
||||
|
||||
* generator/OpaqueGen.cs (Generate): Tweak the generated Ref/Unref
|
||||
a bit; only Ref the pointer if Owned is false (and then set it to
|
||||
true), and vice versa for Unref.
|
||||
|
||||
* glib/Opaque.cs (Opaque): set owned before setting Raw, so
|
||||
that Raw will be reffed properly.
|
||||
(GetOpaque): Fix this up to dtrt in all cases with refcounted
|
||||
opaques.
|
||||
|
||||
* gtk/TreeView.custom (GetPathAtPos): Use "GetOpaque(...)" rather
|
||||
than "new TreePath()"
|
||||
|
||||
* sample/opaquetest/*: regression test for opaque free/ref/unref
|
||||
handling
|
||||
|
||||
* sample/Makefile.am (SUBDIRS): add opaquetest
|
||||
|
||||
* configure.in.in (AC_OUTPUT): add opaquetest files
|
||||
|
||||
2005-08-04 Dan Winship <danw@novell.com>
|
||||
|
||||
Change the way generatable validation works. Some generatable
|
||||
|
|
|
@ -313,6 +313,8 @@ sample/rsvg/Makefile
|
|||
sample/test/Makefile
|
||||
sample/valtest/Makefile
|
||||
sample/valtest/valtest.exe.config
|
||||
sample/opaquetest/Makefile
|
||||
sample/opaquetest/opaquetest.exe.config
|
||||
sample/cairo-sample.exe.config
|
||||
])
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@
|
|||
<Docs>
|
||||
<summary>Whether or not this <see cref="T:GLib.Opaque" /> wrapper owns the raw object.</summary>
|
||||
<value>
|
||||
<see langword="true" /> if the wrapper owns the raw object.</value>
|
||||
<see langword="true" /> if the wrapper owns the raw object and will <see cref="M:GLib.Opaque.Unref"/> / <see cref="M:GLib.Opaque.Free"/> it when the wrapper is disposed.</value>
|
||||
<remarks>By default, this is set to <see langword="true" /> for opaque objects created with the no-argument constructor, and <see langword="false" /> for opaque objects created with the <see cref="T:System.IntPtr" /> constructor. Methods that return an opaque object can override this by setting the <see cref="M:GLib.Opaque.Owned" /> property accordingly to obey the memory-management conventions of the underlying C code.</remarks>
|
||||
</Docs>
|
||||
</Member>
|
||||
|
|
|
@ -78,7 +78,10 @@ namespace GtkSharp.Generation {
|
|||
ref_.GenerateImport (sw);
|
||||
sw.WriteLine ("\t\tprotected override void Ref (IntPtr raw)");
|
||||
sw.WriteLine ("\t\t{");
|
||||
sw.WriteLine ("\t\t\t" + ref_.CName + " (raw);");
|
||||
sw.WriteLine ("\t\t\tif (!Owned) {");
|
||||
sw.WriteLine ("\t\t\t\t" + ref_.CName + " (raw);");
|
||||
sw.WriteLine ("\t\t\t\tOwned = true;");
|
||||
sw.WriteLine ("\t\t\t}");
|
||||
sw.WriteLine ("\t\t}");
|
||||
sw.WriteLine ();
|
||||
|
||||
|
@ -95,7 +98,10 @@ namespace GtkSharp.Generation {
|
|||
unref.GenerateImport (sw);
|
||||
sw.WriteLine ("\t\tprotected override void Unref (IntPtr raw)");
|
||||
sw.WriteLine ("\t\t{");
|
||||
sw.WriteLine ("\t\t\t" + unref.CName + " (raw);");
|
||||
sw.WriteLine ("\t\t\tif (Owned) {");
|
||||
sw.WriteLine ("\t\t\t\t" + unref.CName + " (raw);");
|
||||
sw.WriteLine ("\t\t\t\tOwned = false;");
|
||||
sw.WriteLine ("\t\t\t}");
|
||||
sw.WriteLine ("\t\t}");
|
||||
sw.WriteLine ();
|
||||
|
||||
|
|
|
@ -65,7 +65,13 @@ namespace GLib {
|
|||
}
|
||||
|
||||
opaque = (Opaque)Activator.CreateInstance (type, new object[] { o });
|
||||
opaque.owned = owned;
|
||||
if (owned) {
|
||||
if (opaque.owned) {
|
||||
// The constructor took a Ref it shouldn't have, so undo it
|
||||
opaque.Unref (o);
|
||||
} else
|
||||
opaque.owned = true;
|
||||
}
|
||||
return opaque;
|
||||
}
|
||||
|
||||
|
@ -76,8 +82,8 @@ namespace GLib {
|
|||
|
||||
public Opaque (IntPtr raw)
|
||||
{
|
||||
Raw = raw;
|
||||
owned = false;
|
||||
Raw = raw;
|
||||
}
|
||||
|
||||
protected IntPtr Raw {
|
||||
|
|
|
@ -81,8 +81,7 @@
|
|||
bool raw_ret = gtk_tree_view_get_path_at_pos (Handle, x, y, out pathHandle, out columnHandle, out cell_x, out cell_y);
|
||||
if (raw_ret) {
|
||||
column = (Gtk.TreeViewColumn) GLib.Object.GetObject (columnHandle, false);
|
||||
path = new TreePath (pathHandle);
|
||||
path.Owned = true;
|
||||
path = (Gtk.TreePath) GLib.Opaque.GetOpaque (pathHandle, typeof (Gtk.TreePath), true);
|
||||
} else {
|
||||
path = null;
|
||||
column = null;
|
||||
|
@ -97,10 +96,9 @@
|
|||
IntPtr pathHandle;
|
||||
IntPtr columnHandle;
|
||||
bool raw_ret = gtk_tree_view_get_path_at_pos_intptr (Handle, x, y, out pathHandle, out columnHandle, IntPtr.Zero, IntPtr.Zero);
|
||||
if (raw_ret) {
|
||||
path = new TreePath (pathHandle);
|
||||
path.Owned = true;
|
||||
} else
|
||||
if (raw_ret)
|
||||
path = (Gtk.TreePath) GLib.Opaque.GetOpaque (pathHandle, typeof (Gtk.TreePath), true);
|
||||
else
|
||||
path = null;
|
||||
|
||||
return raw_ret;
|
||||
|
@ -112,8 +110,7 @@
|
|||
IntPtr columnHandle;
|
||||
bool raw_ret = gtk_tree_view_get_path_at_pos_intptr (Handle, x, y, out pathHandle, out columnHandle, IntPtr.Zero, IntPtr.Zero);
|
||||
if (raw_ret) {
|
||||
path = new TreePath (pathHandle);
|
||||
path.Owned = true;
|
||||
path = (Gtk.TreePath) GLib.Opaque.GetOpaque (pathHandle, typeof (Gtk.TreePath), true);
|
||||
column = (Gtk.TreeViewColumn) GLib.Object.GetObject (columnHandle, false);
|
||||
} else {
|
||||
path = null;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
SUBDIRS = gconf rsvg test GtkDemo pixmaps gnomevfs valtest
|
||||
SUBDIRS = gconf rsvg test GtkDemo pixmaps gnomevfs valtest opaquetest
|
||||
|
||||
if ENABLE_GNOME
|
||||
GNOME_TARGETS=gnome-hello-world.exe canvas-example.exe fifteen.exe print.exe
|
||||
|
|
30
sample/opaquetest/Makefile.am
Normal file
30
sample/opaquetest/Makefile.am
Normal file
|
@ -0,0 +1,30 @@
|
|||
noinst_SCRIPTS = opaquetest.exe
|
||||
lib_LTLIBRARIES = libopaque.la
|
||||
|
||||
assemblies=../../glib/glib-sharp.dll ../../pango/pango-sharp.dll ../../atk/atk-sharp.dll ../../gdk/gdk-sharp.dll ../../gtk/gtk-sharp.dll
|
||||
references=$(addprefix /r:, $(assemblies))
|
||||
|
||||
opaquetest.exe: OpaqueTest.cs generated/*.cs $(assemblies)
|
||||
$(CSC) /out:opaquetest.exe $(references) $(srcdir)/OpaqueTest.cs generated/*.cs
|
||||
|
||||
libopaque_la_SOURCES = \
|
||||
opaques.c \
|
||||
opaques.h
|
||||
|
||||
libopaque_la_LDFLAGS = -module -avoid-version -no-undefined
|
||||
|
||||
libopaque_la_LIBADD = $(GTK_LIBS)
|
||||
|
||||
INCLUDES = $(GTK_CFLAGS)
|
||||
|
||||
generated/*.cs: opaque-api.xml
|
||||
$(RUNTIME) ../../generator/gapi_codegen.exe --generate opaque-api.xml --include ../../gtk/gtk-api.xml ../../gdk/gdk-api.xml --outdir=generated --assembly-name=opaque-sharp
|
||||
|
||||
api:
|
||||
PATH=../../parser:$PATH $(RUNTIME) ../../parser/gapi-parser.exe opaque-sources.xml
|
||||
$(RUNTIME) ../../parser/gapi-fixup.exe --metadata=Opaque.metadata --api=opaque-api.xml
|
||||
|
||||
install:
|
||||
|
||||
CLEANFILES = \
|
||||
generated/*.cs
|
5
sample/opaquetest/Opaque.metadata
Normal file
5
sample/opaquetest/Opaque.metadata
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0"?>
|
||||
<metadata>
|
||||
<attr path="/api/namespace/struct[@name='Opaque']" name="opaque">1</attr>
|
||||
<attr path="/api/namespace/struct[@name='Refcounted']" name="opaque">1</attr>
|
||||
</metadata>
|
282
sample/opaquetest/OpaqueTest.cs
Normal file
282
sample/opaquetest/OpaqueTest.cs
Normal file
|
@ -0,0 +1,282 @@
|
|||
// Opaquetest.cs: GLib.Opaque regression test
|
||||
//
|
||||
// Copyright (c) 2005 Novell, Inc.
|
||||
|
||||
using Gtksharp;
|
||||
using System;
|
||||
|
||||
public class OpaqueTest {
|
||||
|
||||
static int errors = 0;
|
||||
|
||||
static void GC ()
|
||||
{
|
||||
System.GC.Collect ();
|
||||
System.GC.WaitForPendingFinalizers ();
|
||||
System.GC.Collect ();
|
||||
System.GC.WaitForPendingFinalizers ();
|
||||
}
|
||||
|
||||
public static int Main ()
|
||||
{
|
||||
Gtk.Application.Init ();
|
||||
|
||||
TestOpaque ();
|
||||
Console.WriteLine ();
|
||||
TestRefcounted ();
|
||||
Console.WriteLine ();
|
||||
|
||||
Console.WriteLine ("{0} errors", errors);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
static Opaque ret_op;
|
||||
|
||||
static Opaque ReturnOpaque ()
|
||||
{
|
||||
return ret_op;
|
||||
}
|
||||
|
||||
static void TestOpaque ()
|
||||
{
|
||||
Opaque op, op1;
|
||||
IntPtr handle;
|
||||
|
||||
Console.WriteLine ("Testing Opaque new/free");
|
||||
op = new Opaque ();
|
||||
if (!op.Owned)
|
||||
Error ("Newly-created Opaque is not Owned");
|
||||
handle = op.Handle;
|
||||
op.Dispose ();
|
||||
op = new Opaque (handle);
|
||||
if (op.Owned)
|
||||
Error ("IntPtr-created Opaque is Owned");
|
||||
if (Opaquetest.Error)
|
||||
Error ("Memory error after initial new/free.");
|
||||
Opaquetest.ExpectError = true;
|
||||
if (op.Serial != Opaque.LastSerial)
|
||||
Error ("Serial mismatch. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
|
||||
if (!Opaquetest.Error)
|
||||
Error ("Opaque not properly freed.");
|
||||
op.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Opaque created from IntPtr was freed by gtk#");
|
||||
|
||||
Console.WriteLine ("Testing Opaque copy/free");
|
||||
op = new Opaque ();
|
||||
op1 = op.Copy ();
|
||||
handle = op1.Handle;
|
||||
op.Dispose ();
|
||||
op1.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Memory error after initial copy/free.");
|
||||
op = new Opaque (handle);
|
||||
Opaquetest.ExpectError = true;
|
||||
if (op.Serial != Opaque.LastSerial)
|
||||
Error ("Serial mismatch. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
|
||||
|
||||
if (!Opaquetest.Error)
|
||||
Error ("Opaque not properly freed.");
|
||||
op.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Opaque created from IntPtr was freed by gtk#");
|
||||
|
||||
Console.WriteLine ("Testing non-owned return.");
|
||||
op = new Opaque ();
|
||||
op1 = new Opaque ();
|
||||
op.Friend = op1;
|
||||
if (Opaquetest.Error)
|
||||
Error ("Memory error after setting op.Friend.");
|
||||
op1 = op.Friend;
|
||||
if (op1.Serial != Opaque.LastSerial || Opaquetest.Error)
|
||||
Error ("Error reading op.Friend. Expected {0}, Got {1}", Opaque.LastSerial, op1.Serial);
|
||||
if (!op1.Owned)
|
||||
Error ("op1 not Owned after being read off op.Friend");
|
||||
op.Dispose ();
|
||||
op1.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Memory error after freeing op and op1.");
|
||||
|
||||
Console.WriteLine ("Testing returning a Gtk#-owned opaque from C# to C");
|
||||
ret_op = new Opaque ();
|
||||
op = Opaque.Check (ReturnOpaque, GC);
|
||||
if (op.Serial != Opaque.LastSerial || Opaquetest.Error)
|
||||
Error ("Error during Opaque.Check. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
|
||||
op.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Memory error after clearing op.");
|
||||
|
||||
Console.WriteLine ("Testing returning a Gtk#-owned opaque to a C method that will free it");
|
||||
ret_op = new Opaque ();
|
||||
op = Opaque.CheckFree (ReturnOpaque, GC);
|
||||
if (Opaquetest.Error)
|
||||
Error ("Error during Opaque.CheckFree.");
|
||||
Opaquetest.ExpectError = true;
|
||||
if (op.Serial != Opaque.LastSerial)
|
||||
Error ("Error during Opaque.CheckFree. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
|
||||
if (!Opaquetest.Error)
|
||||
Error ("Didn't get expected error accessing op.Serial!");
|
||||
Opaquetest.ExpectError = true;
|
||||
op.Dispose ();
|
||||
if (!Opaquetest.Error)
|
||||
Error ("Didn't get expected double free on op after CheckFree!");
|
||||
|
||||
Console.WriteLine ("Testing leaking a C-owned opaque");
|
||||
ret_op = new Opaque ();
|
||||
ret_op.Owned = false;
|
||||
op = Opaque.Check (ReturnOpaque, GC);
|
||||
if (op.Serial != Opaque.LastSerial || Opaquetest.Error)
|
||||
Error ("Error during Opaque.Check. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
|
||||
handle = op.Handle;
|
||||
op.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Memory error after disposing op.");
|
||||
op = new Opaque (handle);
|
||||
if (op.Serial != Opaque.LastSerial || Opaquetest.Error)
|
||||
Error ("Failed to leak op. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
|
||||
|
||||
Console.WriteLine ("Testing handing over a C-owned opaque to a C method that will free it");
|
||||
ret_op = new Opaque ();
|
||||
ret_op.Owned = false;
|
||||
op = Opaque.CheckFree (ReturnOpaque, GC);
|
||||
if (Opaquetest.Error)
|
||||
Error ("Error during Opaque.CheckFree.");
|
||||
Opaquetest.ExpectError = true;
|
||||
if (op.Serial != Opaque.LastSerial)
|
||||
Error ("Error during Opaque.CheckFree. Expected {0}, Got {1}", Opaque.LastSerial, op.Serial);
|
||||
if (!Opaquetest.Error)
|
||||
Error ("Didn't get expected error accessing op.Serial!");
|
||||
op.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Double free on op!");
|
||||
}
|
||||
|
||||
static Refcounted ret_ref;
|
||||
|
||||
static Refcounted ReturnRefcounted ()
|
||||
{
|
||||
return ret_ref;
|
||||
}
|
||||
|
||||
static void TestRefcounted ()
|
||||
{
|
||||
Refcounted ref1, ref2;
|
||||
IntPtr handle;
|
||||
|
||||
Console.WriteLine ("Testing Refcounted new/free");
|
||||
ref1 = new Refcounted ();
|
||||
if (!ref1.Owned)
|
||||
Error ("Newly-created Refcounted is not Owned");
|
||||
handle = ref1.Handle;
|
||||
ref1.Dispose ();
|
||||
Opaquetest.ExpectError = true;
|
||||
ref1 = new Refcounted (handle);
|
||||
if (!Opaquetest.Error)
|
||||
Error ("Didn't get expected ref error resurrecting ref1.");
|
||||
if (!ref1.Owned)
|
||||
Error ("IntPtr-created Refcounted is not Owned");
|
||||
Opaquetest.ExpectError = true;
|
||||
if (ref1.Serial != Refcounted.LastSerial)
|
||||
Error ("Serial mismatch. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
|
||||
// We caused it to take a ref on the "freed" underlying object, so
|
||||
// undo that now so it doesn't cause an error later when we're not
|
||||
// expecting it.
|
||||
Opaquetest.ExpectError = true;
|
||||
ref1.Dispose ();
|
||||
Opaquetest.Error = false;
|
||||
|
||||
Console.WriteLine ("Testing Refcounted leak/non-free");
|
||||
ref1 = new Refcounted ();
|
||||
ref1.Owned = false;
|
||||
handle = ref1.Handle;
|
||||
ref1.Dispose ();
|
||||
ref1 = new Refcounted (handle);
|
||||
if (Opaquetest.Error)
|
||||
Error ("Non-owned ref was freed by gtk#");
|
||||
if (ref1.Serial != Refcounted.LastSerial)
|
||||
Error ("Serial mismatch. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
|
||||
if (Opaquetest.Error)
|
||||
Error ("Non-owned ref was freed by gtk#");
|
||||
|
||||
Console.WriteLine ("Testing non-owned return.");
|
||||
ref1 = new Refcounted ();
|
||||
ref2 = new Refcounted ();
|
||||
ref1.Friend = ref2;
|
||||
if (Opaquetest.Error)
|
||||
Error ("Memory error after setting ref1.Friend.");
|
||||
if (ref2.Refcount != 2)
|
||||
Error ("Refcount wrong for ref2 after setting ref1.Friend. Expected 2, Got {0}", ref2.Refcount);
|
||||
ref2.Dispose ();
|
||||
ref2 = ref1.Friend;
|
||||
if (ref2.Serial != Refcounted.LastSerial || Opaquetest.Error)
|
||||
Error ("Error reading ref1.Friend. Expected {0}, Got {1}", Refcounted.LastSerial, ref2.Serial);
|
||||
if (ref2.Refcount != 2 || Opaquetest.Error)
|
||||
Error ("Refcount wrong for ref2 after reading ref1.Friend. Expected 2, Got {0}", ref2.Refcount);
|
||||
if (!ref2.Owned)
|
||||
Error ("ref2 not Owned after being read off ref1.Friend");
|
||||
ref1.Dispose ();
|
||||
ref2.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Memory error after freeing ref1 and ref2.");
|
||||
|
||||
Console.WriteLine ("Testing returning a Gtk#-owned refcounted from C# to C");
|
||||
ret_ref = new Refcounted ();
|
||||
ref1 = Refcounted.Check (ReturnRefcounted, GC);
|
||||
if (ref1.Serial != Refcounted.LastSerial || Opaquetest.Error)
|
||||
Error ("Error during Refcounted.Check. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
|
||||
ref1.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Memory error after clearing ref1.");
|
||||
|
||||
Console.WriteLine ("Testing returning a Gtk#-owned refcounted to a C method that will free it");
|
||||
ret_ref = new Refcounted ();
|
||||
ref1 = Refcounted.CheckUnref (ReturnRefcounted, GC);
|
||||
if (Opaquetest.Error)
|
||||
Error ("Error during Refcounted.CheckUnref.");
|
||||
Opaquetest.ExpectError = true;
|
||||
if (ref1.Serial != Refcounted.LastSerial)
|
||||
Error ("Error during Refcounted.CheckUnref. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
|
||||
if (!Opaquetest.Error)
|
||||
Error ("Didn't get expected error accessing ref1.Serial!");
|
||||
Opaquetest.ExpectError = true;
|
||||
ref1.Dispose ();
|
||||
if (!Opaquetest.Error)
|
||||
Error ("Didn't get expected double free on ref1 after CheckUnref!");
|
||||
|
||||
Console.WriteLine ("Testing leaking a C-owned refcounted");
|
||||
ret_ref = new Refcounted ();
|
||||
ret_ref.Owned = false;
|
||||
ref1 = Refcounted.Check (ReturnRefcounted, GC);
|
||||
if (ref1.Serial != Refcounted.LastSerial || Opaquetest.Error)
|
||||
Error ("Error during Refcounted.Check. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
|
||||
handle = ref1.Handle;
|
||||
ref1.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Memory error after disposing ref1.");
|
||||
ref1 = new Refcounted (handle);
|
||||
if (ref1.Serial != Refcounted.LastSerial || Opaquetest.Error)
|
||||
Error ("Failed to leak ref1. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
|
||||
|
||||
Console.WriteLine ("Testing handing over a C-owned refcounted to a C method that will free it");
|
||||
ret_ref = new Refcounted ();
|
||||
ret_ref.Owned = false;
|
||||
ref1 = Refcounted.CheckUnref (ReturnRefcounted, GC);
|
||||
if (Opaquetest.Error)
|
||||
Error ("Error during Refcounted.CheckUnref.");
|
||||
Opaquetest.ExpectError = true;
|
||||
if (ref1.Serial != Refcounted.LastSerial)
|
||||
Error ("Error during Refcounted.CheckUnref. Expected {0}, Got {1}", Refcounted.LastSerial, ref1.Serial);
|
||||
if (!Opaquetest.Error)
|
||||
Error ("Didn't get expected error accessing ref1.Serial!");
|
||||
ref1.Dispose ();
|
||||
if (Opaquetest.Error)
|
||||
Error ("Double free on ref1!");
|
||||
}
|
||||
|
||||
static void Error (string message, params object[] args)
|
||||
{
|
||||
Console.Error.WriteLine (" MANAGED ERROR: " + message, args);
|
||||
errors++;
|
||||
}
|
||||
}
|
123
sample/opaquetest/opaque-api.xml
Normal file
123
sample/opaquetest/opaque-api.xml
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?xml version="1.0"?>
|
||||
<api>
|
||||
<!--
|
||||
|
||||
This file was automatically generated.
|
||||
Please DO NOT MODIFY THIS FILE, modify .metadata files instead.
|
||||
|
||||
-->
|
||||
<namespace name="Gtksharp" library="libopaque.dll">
|
||||
<callback name="GCFunc" cname="GtksharpGCFunc">
|
||||
<return-type type="void" />
|
||||
</callback>
|
||||
<callback name="OpaqueReturnFunc" cname="GtksharpOpaqueReturnFunc">
|
||||
<return-type type="GtksharpOpaque*" />
|
||||
</callback>
|
||||
<callback name="RefcountedReturnFunc" cname="GtksharpRefcountedReturnFunc">
|
||||
<return-type type="GtksharpRefcounted*" />
|
||||
</callback>
|
||||
<struct name="Opaque" cname="GtksharpOpaque" opaque="1">
|
||||
<field name="Serial" cname="serial" type="int" />
|
||||
<field name="Valid" cname="valid" type="gboolean" />
|
||||
<field name="Friend" cname="friend" type="GtksharpOpaque*" />
|
||||
<method name="Check" cname="gtksharp_opaque_check" shared="true">
|
||||
<return-type type="GtksharpOpaque*" />
|
||||
<parameters>
|
||||
<parameter type="GtksharpOpaqueReturnFunc" name="func" />
|
||||
<parameter type="GtksharpGCFunc" name="gc" />
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="CheckFree" cname="gtksharp_opaque_check_free" shared="true">
|
||||
<return-type type="GtksharpOpaque*" />
|
||||
<parameters>
|
||||
<parameter type="GtksharpOpaqueReturnFunc" name="func" />
|
||||
<parameter type="GtksharpGCFunc" name="gc" />
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="Copy" cname="gtksharp_opaque_copy">
|
||||
<return-type type="GtksharpOpaque*" owned="true" />
|
||||
</method>
|
||||
<method name="Free" cname="gtksharp_opaque_free">
|
||||
<return-type type="void" />
|
||||
</method>
|
||||
<method name="GetFriend" cname="gtksharp_opaque_get_friend">
|
||||
<return-type type="GtksharpOpaque*" />
|
||||
</method>
|
||||
<method name="GetLastSerial" cname="gtksharp_opaque_get_last_serial" shared="true">
|
||||
<return-type type="int" />
|
||||
</method>
|
||||
<method name="GetSerial" cname="gtksharp_opaque_get_serial">
|
||||
<return-type type="int" />
|
||||
</method>
|
||||
<constructor cname="gtksharp_opaque_new" />
|
||||
<method name="SetFriend" cname="gtksharp_opaque_set_friend">
|
||||
<return-type type="void" />
|
||||
<parameters>
|
||||
<parameter type="GtksharpOpaque*" name="friend" />
|
||||
</parameters>
|
||||
</method>
|
||||
</struct>
|
||||
<struct name="Refcounted" cname="GtksharpRefcounted" opaque="1">
|
||||
<field name="Serial" cname="serial" type="int" />
|
||||
<field name="Refcount" cname="refcount" type="int" />
|
||||
<field name="Valid" cname="valid" type="gboolean" />
|
||||
<field name="Friend" cname="friend" type="GtksharpRefcounted*" />
|
||||
<method name="Check" cname="gtksharp_refcounted_check" shared="true">
|
||||
<return-type type="GtksharpRefcounted*" />
|
||||
<parameters>
|
||||
<parameter type="GtksharpRefcountedReturnFunc" name="func" />
|
||||
<parameter type="GtksharpGCFunc" name="gc" />
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="CheckUnref" cname="gtksharp_refcounted_check_unref" shared="true">
|
||||
<return-type type="GtksharpRefcounted*" />
|
||||
<parameters>
|
||||
<parameter type="GtksharpRefcountedReturnFunc" name="func" />
|
||||
<parameter type="GtksharpGCFunc" name="gc" />
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="GetFriend" cname="gtksharp_refcounted_get_friend">
|
||||
<return-type type="GtksharpRefcounted*" />
|
||||
</method>
|
||||
<method name="GetLastSerial" cname="gtksharp_refcounted_get_last_serial" shared="true">
|
||||
<return-type type="int" />
|
||||
</method>
|
||||
<method name="GetRefcount" cname="gtksharp_refcounted_get_refcount">
|
||||
<return-type type="int" />
|
||||
</method>
|
||||
<method name="GetSerial" cname="gtksharp_refcounted_get_serial">
|
||||
<return-type type="int" />
|
||||
</method>
|
||||
<constructor cname="gtksharp_refcounted_new" />
|
||||
<method name="Ref" cname="gtksharp_refcounted_ref">
|
||||
<return-type type="void" />
|
||||
</method>
|
||||
<method name="SetFriend" cname="gtksharp_refcounted_set_friend">
|
||||
<return-type type="void" />
|
||||
<parameters>
|
||||
<parameter type="GtksharpRefcounted*" name="friend" />
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="Unref" cname="gtksharp_refcounted_unref">
|
||||
<return-type type="void" />
|
||||
</method>
|
||||
</struct>
|
||||
<class name="Opaquetest" cname="GtksharpOpaquetest_">
|
||||
<method name="GetError" cname="gtksharp_opaquetest_get_error" shared="true">
|
||||
<return-type type="gboolean" />
|
||||
</method>
|
||||
<method name="SetError" cname="gtksharp_opaquetest_set_error" shared="true">
|
||||
<return-type type="void" />
|
||||
<parameters>
|
||||
<parameter type="gboolean" name="err" />
|
||||
</parameters>
|
||||
</method>
|
||||
<method name="SetExpectError" cname="gtksharp_opaquetest_set_expect_error" shared="true">
|
||||
<return-type type="void" />
|
||||
<parameters>
|
||||
<parameter type="gboolean" name="err" />
|
||||
</parameters>
|
||||
</method>
|
||||
</class>
|
||||
</namespace>
|
||||
</api>
|
9
sample/opaquetest/opaque-sources.xml
Normal file
9
sample/opaquetest/opaque-sources.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<gapi-parser-input>
|
||||
<api filename="opaque-api.xml">
|
||||
<library name="libopaque.dll">
|
||||
<namespace name="Gtksharp">
|
||||
<dir>.</dir>
|
||||
</namespace>
|
||||
</library>
|
||||
</api>
|
||||
</gapi-parser-input>
|
226
sample/opaquetest/opaques.c
Normal file
226
sample/opaquetest/opaques.c
Normal file
|
@ -0,0 +1,226 @@
|
|||
/* opaques.c: Opaque memory management test objects
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "opaques.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static int opserial, refserial;
|
||||
static gboolean error = FALSE, expect_error = FALSE;
|
||||
|
||||
static gboolean check_error (gboolean valid, const char *msg, ...);
|
||||
|
||||
GtksharpOpaque *
|
||||
gtksharp_opaque_new (void)
|
||||
{
|
||||
GtksharpOpaque *op = g_new0 (GtksharpOpaque, 1);
|
||||
op->valid = TRUE;
|
||||
op->serial = opserial++;
|
||||
return op;
|
||||
}
|
||||
|
||||
int
|
||||
gtksharp_opaque_get_serial (GtksharpOpaque *op)
|
||||
{
|
||||
check_error (op->valid, "get_serial on freed GtksharpOpaque serial %d\n", op->serial);
|
||||
return op->serial;
|
||||
}
|
||||
|
||||
void gtksharp_opaque_set_friend (GtksharpOpaque *op, GtksharpOpaque *friend)
|
||||
{
|
||||
check_error (op->valid, "set_friend on freed GtksharpOpaque serial %d\n", op->serial);
|
||||
op->friend = friend;
|
||||
}
|
||||
|
||||
GtksharpOpaque *
|
||||
gtksharp_opaque_get_friend (GtksharpOpaque *op)
|
||||
{
|
||||
check_error (op->valid, "get_friend on freed GtksharpOpaque serial %d\n", op->serial);
|
||||
return op->friend;
|
||||
}
|
||||
|
||||
GtksharpOpaque *
|
||||
gtksharp_opaque_copy (GtksharpOpaque *op)
|
||||
{
|
||||
check_error (op->valid, "copying freed GtksharpOpaque serial %d\n", op->serial);
|
||||
return gtksharp_opaque_new ();
|
||||
}
|
||||
|
||||
void
|
||||
gtksharp_opaque_free (GtksharpOpaque *op)
|
||||
{
|
||||
check_error (op->valid, "Double free of GtksharpOpaque serial %d\n", op->serial);
|
||||
op->valid = FALSE;
|
||||
/* We don't actually free it */
|
||||
}
|
||||
|
||||
GtksharpOpaque *
|
||||
gtksharp_opaque_check (GtksharpOpaqueReturnFunc func, GtksharpGCFunc gc)
|
||||
{
|
||||
GtksharpOpaque *op = func ();
|
||||
gc ();
|
||||
return op;
|
||||
}
|
||||
|
||||
GtksharpOpaque *
|
||||
gtksharp_opaque_check_free (GtksharpOpaqueReturnFunc func, GtksharpGCFunc gc)
|
||||
{
|
||||
GtksharpOpaque *op = func ();
|
||||
gc ();
|
||||
gtksharp_opaque_free (op);
|
||||
gc ();
|
||||
return op;
|
||||
}
|
||||
|
||||
int
|
||||
gtksharp_opaque_get_last_serial (void)
|
||||
{
|
||||
return opserial - 1;
|
||||
}
|
||||
|
||||
|
||||
GtksharpRefcounted *
|
||||
gtksharp_refcounted_new (void)
|
||||
{
|
||||
GtksharpRefcounted *ref = g_new0 (GtksharpRefcounted, 1);
|
||||
ref->valid = TRUE;
|
||||
ref->refcount = 1;
|
||||
ref->serial = refserial++;
|
||||
return ref;
|
||||
}
|
||||
|
||||
int
|
||||
gtksharp_refcounted_get_serial (GtksharpRefcounted *ref)
|
||||
{
|
||||
check_error (ref->valid, "get_serial on freed GtksharpRefcounted serial %d\n", ref->serial);
|
||||
return ref->serial;
|
||||
}
|
||||
|
||||
void
|
||||
gtksharp_refcounted_ref (GtksharpRefcounted *ref)
|
||||
{
|
||||
if (check_error (ref->valid, "ref on freed GtksharpRefcounted serial %d\n", ref->serial))
|
||||
return;
|
||||
ref->refcount++;
|
||||
}
|
||||
|
||||
void
|
||||
gtksharp_refcounted_unref (GtksharpRefcounted *ref)
|
||||
{
|
||||
if (check_error (ref->valid, "unref on freed GtksharpRefcounted serial %d\n", ref->serial))
|
||||
return;
|
||||
if (--ref->refcount == 0) {
|
||||
ref->valid = FALSE;
|
||||
/* We don't actually free it */
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
gtksharp_refcounted_get_refcount (GtksharpRefcounted *ref)
|
||||
{
|
||||
check_error (ref->valid, "get_refcount on freed GtksharpRefcounted serial %d\n", ref->serial);
|
||||
return ref->refcount;
|
||||
}
|
||||
|
||||
void
|
||||
gtksharp_refcounted_set_friend (GtksharpRefcounted *ref, GtksharpRefcounted *friend)
|
||||
{
|
||||
check_error (ref->valid, "set_friend on freed GtksharpRefcounted serial %d\n", ref->serial);
|
||||
if (ref->friend)
|
||||
gtksharp_refcounted_unref (ref->friend);
|
||||
ref->friend = friend;
|
||||
if (ref->friend)
|
||||
gtksharp_refcounted_ref (ref->friend);
|
||||
}
|
||||
|
||||
GtksharpRefcounted *
|
||||
gtksharp_refcounted_get_friend (GtksharpRefcounted *ref)
|
||||
{
|
||||
check_error (ref->valid, "get_friend on freed GtksharpRefcounted serial %d\n", ref->serial);
|
||||
return ref->friend;
|
||||
}
|
||||
|
||||
GtksharpRefcounted *
|
||||
gtksharp_refcounted_check (GtksharpRefcountedReturnFunc func, GtksharpGCFunc gc)
|
||||
{
|
||||
GtksharpRefcounted *ref = func ();
|
||||
gc ();
|
||||
return ref;
|
||||
}
|
||||
|
||||
GtksharpRefcounted *
|
||||
gtksharp_refcounted_check_unref (GtksharpRefcountedReturnFunc func, GtksharpGCFunc gc)
|
||||
{
|
||||
GtksharpRefcounted *ref = func ();
|
||||
gc ();
|
||||
gtksharp_refcounted_unref (ref);
|
||||
gc ();
|
||||
return ref;
|
||||
}
|
||||
|
||||
int
|
||||
gtksharp_refcounted_get_last_serial (void)
|
||||
{
|
||||
return refserial - 1;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
check_error (gboolean valid, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (valid)
|
||||
return FALSE;
|
||||
|
||||
error = TRUE;
|
||||
if (expect_error) {
|
||||
expect_error = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
expect_error = FALSE;
|
||||
|
||||
fprintf (stderr, " UNMANAGED ERROR: ");
|
||||
va_start (ap, msg);
|
||||
vfprintf (stderr, msg, ap);
|
||||
va_end (ap);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
gtksharp_opaquetest_get_error (void)
|
||||
{
|
||||
gboolean old_error = error;
|
||||
error = expect_error = FALSE;
|
||||
return old_error;
|
||||
}
|
||||
|
||||
void
|
||||
gtksharp_opaquetest_set_error (gboolean err)
|
||||
{
|
||||
error = err;
|
||||
}
|
||||
|
||||
void
|
||||
gtksharp_opaquetest_set_expect_error (gboolean err)
|
||||
{
|
||||
expect_error = err;
|
||||
}
|
70
sample/opaquetest/opaques.h
Normal file
70
sample/opaquetest/opaques.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/*
|
||||
* Copyright (C) 2000-2003, Ximian, Inc.
|
||||
*/
|
||||
|
||||
#ifndef GTKSHARP_OPAQUES_H
|
||||
#define GTKSHARP_OPAQUES_H 1
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
typedef void (*GtksharpGCFunc) (void);
|
||||
|
||||
typedef struct GtksharpOpaque GtksharpOpaque;
|
||||
struct GtksharpOpaque {
|
||||
int serial;
|
||||
gboolean valid;
|
||||
|
||||
GtksharpOpaque *friend;
|
||||
};
|
||||
|
||||
typedef GtksharpOpaque *(*GtksharpOpaqueReturnFunc) (void);
|
||||
|
||||
GtksharpOpaque *gtksharp_opaque_new (void);
|
||||
int gtksharp_opaque_get_serial (GtksharpOpaque *op);
|
||||
void gtksharp_opaque_set_friend (GtksharpOpaque *op,
|
||||
GtksharpOpaque *friend);
|
||||
GtksharpOpaque *gtksharp_opaque_get_friend (GtksharpOpaque *op);
|
||||
GtksharpOpaque *gtksharp_opaque_copy (GtksharpOpaque *op);
|
||||
void gtksharp_opaque_free (GtksharpOpaque *op);
|
||||
|
||||
GtksharpOpaque *gtksharp_opaque_check (GtksharpOpaqueReturnFunc func,
|
||||
GtksharpGCFunc gc);
|
||||
GtksharpOpaque *gtksharp_opaque_check_free (GtksharpOpaqueReturnFunc func,
|
||||
GtksharpGCFunc gc);
|
||||
|
||||
int gtksharp_opaque_get_last_serial (void);
|
||||
|
||||
|
||||
typedef struct GtksharpRefcounted GtksharpRefcounted;
|
||||
struct GtksharpRefcounted {
|
||||
int serial, refcount;
|
||||
gboolean valid;
|
||||
|
||||
GtksharpRefcounted *friend;
|
||||
};
|
||||
|
||||
typedef GtksharpRefcounted *(*GtksharpRefcountedReturnFunc) (void);
|
||||
|
||||
GtksharpRefcounted *gtksharp_refcounted_new (void);
|
||||
int gtksharp_refcounted_get_serial (GtksharpRefcounted *ref);
|
||||
void gtksharp_refcounted_ref (GtksharpRefcounted *ref);
|
||||
void gtksharp_refcounted_unref (GtksharpRefcounted *ref);
|
||||
int gtksharp_refcounted_get_refcount (GtksharpRefcounted *ref);
|
||||
void gtksharp_refcounted_set_friend (GtksharpRefcounted *ref,
|
||||
GtksharpRefcounted *friend);
|
||||
GtksharpRefcounted *gtksharp_refcounted_get_friend (GtksharpRefcounted *ref);
|
||||
|
||||
GtksharpRefcounted *gtksharp_refcounted_check (GtksharpRefcountedReturnFunc func,
|
||||
GtksharpGCFunc gc);
|
||||
GtksharpRefcounted *gtksharp_refcounted_check_unref (GtksharpRefcountedReturnFunc func,
|
||||
GtksharpGCFunc gc);
|
||||
|
||||
int gtksharp_refcounted_get_last_serial (void);
|
||||
|
||||
|
||||
gboolean gtksharp_opaquetest_get_error (void);
|
||||
void gtksharp_opaquetest_set_error (gboolean err);
|
||||
void gtksharp_opaquetest_set_expect_error (gboolean err);
|
||||
|
||||
#endif /* GTKSHARP_OPAQUES_H */
|
3
sample/opaquetest/opaquetest.exe.config.in
Normal file
3
sample/opaquetest/opaquetest.exe.config.in
Normal file
|
@ -0,0 +1,3 @@
|
|||
<configuration>
|
||||
<dllmap dll="libopaque.dll" target=".libs/libopaque@LIB_PREFIX@@LIB_SUFFIX@"/>
|
||||
</configuration>
|
Loading…
Reference in a new issue