mirror of
https://github.com/Ryujinx/GtkSharp.git
synced 2025-05-11 21:52:16 +00:00
2008-04-30 Mike Kestner <mkestner@novell.com>
* generator/InterfaceGen.cs: * generator/Signal.cs: use generic signal marshaling instead of generating signature specific marshaling callbacks. * glib/glue/closure.c: glue for new closure impl. * glib/Object.cs: open up a couple hashes internally. * glib/Signal.cs: hook in closure based connection and expose EmissionHook functionality for atk usage. * glib/SignalClosure.cs: new generic signal marshaling mechanism. * glib/ToggleRef.cs: null guarding in Target and let Signal remove itself from hash when it disposes itself. svn path=/trunk/gtk-sharp/; revision=102241
This commit is contained in:
parent
a3f799ceb0
commit
0780ed3c0d
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2008-04-30 Mike Kestner <mkestner@novell.com>
|
||||||
|
|
||||||
|
* generator/InterfaceGen.cs:
|
||||||
|
* generator/Signal.cs: use generic signal marshaling instead of
|
||||||
|
generating signature specific marshaling callbacks.
|
||||||
|
* glib/glue/closure.c: glue for new closure impl.
|
||||||
|
* glib/Object.cs: open up a couple hashes internally.
|
||||||
|
* glib/Signal.cs: hook in closure based connection and expose
|
||||||
|
EmissionHook functionality for atk usage.
|
||||||
|
* glib/SignalClosure.cs: new generic signal marshaling mechanism.
|
||||||
|
* glib/ToggleRef.cs: null guarding in Target and let Signal remove
|
||||||
|
itself from hash when it disposes itself.
|
||||||
|
|
||||||
2008-04-30 Mike Kestner <mkestner@novell.com>
|
2008-04-30 Mike Kestner <mkestner@novell.com>
|
||||||
|
|
||||||
* parser/gapi2xml.pl: put class struct field in the signal elems.
|
* parser/gapi2xml.pl: put class struct field in the signal elems.
|
||||||
|
|
|
@ -259,10 +259,8 @@ namespace GtkSharp.Generation {
|
||||||
|
|
||||||
GenProperties (gen_info, null);
|
GenProperties (gen_info, null);
|
||||||
|
|
||||||
foreach (Signal sig in sigs.Values) {
|
foreach (Signal sig in sigs.Values)
|
||||||
sig.GenCallback (sw);
|
|
||||||
sig.GenEvent (sw, null, "GLib.Object.GetObject (Handle)");
|
sig.GenEvent (sw, null, "GLib.Object.GetObject (Handle)");
|
||||||
}
|
|
||||||
|
|
||||||
Method temp = methods ["GetType"] as Method;
|
Method temp = methods ["GetType"] as Method;
|
||||||
if (temp != null)
|
if (temp != null)
|
||||||
|
|
|
@ -85,35 +85,6 @@ namespace GtkSharp.Generation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string CallbackName {
|
|
||||||
get {
|
|
||||||
return Name + "SignalCallback";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string CallbackSig {
|
|
||||||
get {
|
|
||||||
string result = "";
|
|
||||||
for (int i = 0; i < parms.Count; i++) {
|
|
||||||
if (i > 0)
|
|
||||||
result += ", ";
|
|
||||||
|
|
||||||
Parameter p = parms [i];
|
|
||||||
if (p.PassAs != "" && !(p.Generatable is StructBase))
|
|
||||||
result += p.PassAs + " ";
|
|
||||||
result += (p.MarshalType + " arg" + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string DelegateName {
|
|
||||||
get {
|
|
||||||
return Name + "SignalDelegate";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string EventArgsName {
|
private string EventArgsName {
|
||||||
get {
|
get {
|
||||||
if (IsEventHandler)
|
if (IsEventHandler)
|
||||||
|
@ -168,7 +139,7 @@ namespace GtkSharp.Generation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsEventHandler {
|
private bool IsEventHandler {
|
||||||
get {
|
get {
|
||||||
return retval.CSType == "void" && parms.Count == 1 && (parms [0].Generatable is ObjectGen || parms [0].Generatable is InterfaceGen);
|
return retval.CSType == "void" && parms.Count == 1 && (parms [0].Generatable is ObjectGen || parms [0].Generatable is InterfaceGen);
|
||||||
}
|
}
|
||||||
|
@ -204,82 +175,6 @@ namespace GtkSharp.Generation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GenArgsInitialization (StreamWriter sw)
|
|
||||||
{
|
|
||||||
if (parms.Count > 1)
|
|
||||||
sw.WriteLine("\t\t\t\targs.Args = new object[" + (parms.Count - 1) + "];");
|
|
||||||
string finish = "";
|
|
||||||
for (int idx = 1; idx < parms.Count; idx++) {
|
|
||||||
Parameter p = parms [idx];
|
|
||||||
IGeneratable igen = p.Generatable;
|
|
||||||
if (p.PassAs != "out") {
|
|
||||||
if (igen is ManualGen) {
|
|
||||||
sw.WriteLine("\t\t\t\tif (arg{0} == IntPtr.Zero)", idx);
|
|
||||||
sw.WriteLine("\t\t\t\t\targs.Args[{0}] = null;", idx - 1);
|
|
||||||
sw.WriteLine("\t\t\t\telse {");
|
|
||||||
sw.WriteLine("\t\t\t\t\targs.Args[" + (idx - 1) + "] = " + p.FromNative ("arg" + idx) + ";");
|
|
||||||
sw.WriteLine("\t\t\t\t}");
|
|
||||||
} else
|
|
||||||
sw.WriteLine("\t\t\t\targs.Args[" + (idx - 1) + "] = " + p.FromNative ("arg" + idx) + ";");
|
|
||||||
}
|
|
||||||
if (igen is StructBase && p.PassAs == "ref")
|
|
||||||
finish += "\t\t\t\tif (arg" + idx + " != IntPtr.Zero) System.Runtime.InteropServices.Marshal.StructureToPtr (args.Args[" + (idx-1) + "], arg" + idx + ", false);\n";
|
|
||||||
else if (p.PassAs != "")
|
|
||||||
finish += "\t\t\t\targ" + idx + " = " + igen.ToNativeReturn ("((" + p.CSType + ")args.Args[" + (idx - 1) + "])") + ";\n";
|
|
||||||
}
|
|
||||||
return finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GenArgsCleanup (StreamWriter sw, string finish)
|
|
||||||
{
|
|
||||||
if (IsVoid && finish.Length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sw.WriteLine("\n\t\t\ttry {");
|
|
||||||
sw.Write (finish);
|
|
||||||
if (!IsVoid) {
|
|
||||||
if (retval.CSType == "bool") {
|
|
||||||
sw.WriteLine ("\t\t\t\tif (args.RetVal == null)");
|
|
||||||
sw.WriteLine ("\t\t\t\t\treturn false;");
|
|
||||||
}
|
|
||||||
sw.WriteLine("\t\t\t\treturn " + SymbolTable.Table.ToNativeReturn (retval.CType, "((" + retval.CSType + ")args.RetVal)") + ";");
|
|
||||||
}
|
|
||||||
sw.WriteLine("\t\t\t} catch (Exception) {");
|
|
||||||
sw.WriteLine ("\t\t\t\tException ex = new Exception (\"args.RetVal or 'out' property unset or set to incorrect type in " + EventHandlerQualifiedName + " callback\");");
|
|
||||||
sw.WriteLine("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (ex, true);");
|
|
||||||
|
|
||||||
sw.WriteLine ("\t\t\t\t// NOTREACHED: above call doesn't return.");
|
|
||||||
sw.WriteLine ("\t\t\t\tthrow ex;");
|
|
||||||
sw.WriteLine("\t\t\t}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GenCallback (StreamWriter sw)
|
|
||||||
{
|
|
||||||
if (IsEventHandler)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sw.WriteLine ("\t\t[GLib.CDeclCallback]");
|
|
||||||
sw.WriteLine ("\t\tdelegate " + retval.ToNativeType + " " + DelegateName + " (" + CallbackSig + ", IntPtr gch);");
|
|
||||||
sw.WriteLine ();
|
|
||||||
sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + CallbackName + " (" + CallbackSig + ", IntPtr gch)");
|
|
||||||
sw.WriteLine("\t\t{");
|
|
||||||
sw.WriteLine("\t\t\t{0} args = new {0} ();", EventArgsQualifiedName);
|
|
||||||
sw.WriteLine("\t\t\ttry {");
|
|
||||||
sw.WriteLine("\t\t\t\tGLib.Signal sig = ((GCHandle) gch).Target as GLib.Signal;");
|
|
||||||
sw.WriteLine("\t\t\t\tif (sig == null)");
|
|
||||||
sw.WriteLine("\t\t\t\t\tthrow new Exception(\"Unknown signal GC handle received \" + gch);");
|
|
||||||
sw.WriteLine();
|
|
||||||
string finish = GenArgsInitialization (sw);
|
|
||||||
sw.WriteLine("\t\t\t\t{0} handler = ({0}) sig.Handler;", EventHandlerQualifiedName);
|
|
||||||
sw.WriteLine("\t\t\t\thandler (GLib.Object.GetObject (arg0), args);");
|
|
||||||
sw.WriteLine("\t\t\t} catch (Exception e) {");
|
|
||||||
sw.WriteLine("\t\t\t\tGLib.ExceptionManager.RaiseUnhandledException (e, false);");
|
|
||||||
sw.WriteLine("\t\t\t}");
|
|
||||||
GenArgsCleanup (sw, finish);
|
|
||||||
sw.WriteLine("\t\t}");
|
|
||||||
sw.WriteLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool NeedNew (ClassBase implementor)
|
private bool NeedNew (ClassBase implementor)
|
||||||
{
|
{
|
||||||
return elem.HasAttribute ("new_flag") ||
|
return elem.HasAttribute ("new_flag") ||
|
||||||
|
@ -384,11 +279,31 @@ namespace GtkSharp.Generation {
|
||||||
sw.WriteLine ("\t\t}\n");
|
sw.WriteLine ("\t\t}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenDefaultHandlerDelegate (StreamWriter sw, ClassBase implementor)
|
private void GenDefaultHandlerDelegate (GenerationInfo gen_info, ClassBase implementor)
|
||||||
{
|
{
|
||||||
|
StreamWriter sw = gen_info.Writer;
|
||||||
|
StreamWriter glue = gen_info.GlueWriter;
|
||||||
|
bool use_glue = false;
|
||||||
|
//bool use_glue = glue != null && implementor == null;
|
||||||
|
string glue_name = String.Empty;
|
||||||
ManagedCallString call = new ManagedCallString (parms);
|
ManagedCallString call = new ManagedCallString (parms);
|
||||||
sw.WriteLine ("\t\t[GLib.CDeclCallback]");
|
sw.WriteLine ("\t\t[GLib.CDeclCallback]");
|
||||||
sw.WriteLine ("\t\tdelegate " + retval.ToNativeType + " " + Name + "VMDelegate (" + parms.ImportSignature + ");\n");
|
sw.WriteLine ("\t\tdelegate " + retval.ToNativeType + " " + Name + "VMDelegate (" + parms.ImportSignature + ");\n");
|
||||||
|
|
||||||
|
if (use_glue) {
|
||||||
|
glue_name = String.Format ("{0}sharp_{1}_{2}", container_type.NS.ToLower ().Replace (".", "_"), container_type.Name.ToLower (), ClassFieldName);
|
||||||
|
sw.WriteLine ("\t\t[DllImport (\"{0}\")]", gen_info.GluelibName);
|
||||||
|
sw.WriteLine ("\t\tstatic extern void {0} (IntPtr gtype, {1}VMDelegate cb);\n", glue_name, Name);
|
||||||
|
glue.WriteLine ("void {0} (GType gtype, gpointer cb);\n", glue_name);
|
||||||
|
glue.WriteLine ("void\n{0} (GType gtype, gpointer cb)", glue_name);
|
||||||
|
glue.WriteLine ("{");
|
||||||
|
glue.WriteLine ("\tGObjectClass *klass = g_type_class_peek (gtype);");
|
||||||
|
glue.WriteLine ("\tif (klass == NULL)");
|
||||||
|
glue.WriteLine ("\t\tklass = g_type_class_ref (gtype);");
|
||||||
|
glue.WriteLine ("\t(({0} *)klass)->{1} = cb;", container_type.CName + "Class", ClassFieldName);
|
||||||
|
glue.WriteLine ("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
sw.WriteLine ("\t\tstatic {0} {1};\n", Name + "VMDelegate", Name + "VMCallback");
|
sw.WriteLine ("\t\tstatic {0} {1};\n", Name + "VMDelegate", Name + "VMCallback");
|
||||||
sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + Name.ToLower() + "_cb (" + parms.ImportSignature + ")");
|
sw.WriteLine ("\t\tstatic " + retval.ToNativeType + " " + Name.ToLower() + "_cb (" + parms.ImportSignature + ")");
|
||||||
sw.WriteLine ("\t\t{");
|
sw.WriteLine ("\t\t{");
|
||||||
|
@ -413,13 +328,16 @@ namespace GtkSharp.Generation {
|
||||||
sw.WriteLine ("\t\t{");
|
sw.WriteLine ("\t\t{");
|
||||||
sw.WriteLine ("\t\t\tif (" + Name + "VMCallback == null)");
|
sw.WriteLine ("\t\t\tif (" + Name + "VMCallback == null)");
|
||||||
sw.WriteLine ("\t\t\t\t" + Name + "VMCallback = new " + Name + "VMDelegate (" + Name.ToLower() + "_cb);");
|
sw.WriteLine ("\t\t\t\t" + Name + "VMCallback = new " + Name + "VMDelegate (" + Name.ToLower() + "_cb);");
|
||||||
sw.WriteLine ("\t\t\tOverrideVirtualMethod (gtype, " + CName + ", " + Name + "VMCallback);");
|
if (use_glue)
|
||||||
|
sw.WriteLine ("\t\t\t{0} (gtype.Val, {1}VMCallback);", glue_name, Name);
|
||||||
|
else
|
||||||
|
sw.WriteLine ("\t\t\tOverrideVirtualMethod (gtype, " + CName + ", " + Name + "VMCallback);");
|
||||||
sw.WriteLine ("\t\t}\n");
|
sw.WriteLine ("\t\t}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GenEvent (StreamWriter sw, ClassBase implementor, string target)
|
public void GenEvent (StreamWriter sw, ClassBase implementor, string target)
|
||||||
{
|
{
|
||||||
string marsh = IsEventHandler ? "" : ", new " + DelegateName + "(" + CallbackName + ")";
|
string args_type = IsEventHandler ? "" : ", typeof (" + EventArgsQualifiedName + ")";
|
||||||
|
|
||||||
sw.WriteLine("\t\t[GLib.Signal("+ CName + ")]");
|
sw.WriteLine("\t\t[GLib.Signal("+ CName + ")]");
|
||||||
sw.Write("\t\tpublic ");
|
sw.Write("\t\tpublic ");
|
||||||
|
@ -427,11 +345,11 @@ namespace GtkSharp.Generation {
|
||||||
sw.Write("new ");
|
sw.Write("new ");
|
||||||
sw.WriteLine("event " + EventHandlerQualifiedName + " " + Name + " {");
|
sw.WriteLine("event " + EventHandlerQualifiedName + " " + Name + " {");
|
||||||
sw.WriteLine("\t\t\tadd {");
|
sw.WriteLine("\t\t\tadd {");
|
||||||
sw.WriteLine("\t\t\t\tGLib.Signal sig = GLib.Signal.Lookup (" + target + ", " + CName + marsh + ");");
|
sw.WriteLine("\t\t\t\tGLib.Signal sig = GLib.Signal.Lookup (" + target + ", " + CName + args_type + ");");
|
||||||
sw.WriteLine("\t\t\t\tsig.AddDelegate (value);");
|
sw.WriteLine("\t\t\t\tsig.AddDelegate (value);");
|
||||||
sw.WriteLine("\t\t\t}");
|
sw.WriteLine("\t\t\t}");
|
||||||
sw.WriteLine("\t\t\tremove {");
|
sw.WriteLine("\t\t\tremove {");
|
||||||
sw.WriteLine("\t\t\t\tGLib.Signal sig = GLib.Signal.Lookup (" + target + ", " + CName + marsh + ");");
|
sw.WriteLine("\t\t\t\tGLib.Signal sig = GLib.Signal.Lookup (" + target + ", " + CName + args_type + ");");
|
||||||
sw.WriteLine("\t\t\t\tsig.RemoveDelegate (value);");
|
sw.WriteLine("\t\t\t\tsig.RemoveDelegate (value);");
|
||||||
sw.WriteLine("\t\t\t}");
|
sw.WriteLine("\t\t\t}");
|
||||||
sw.WriteLine("\t\t}");
|
sw.WriteLine("\t\t}");
|
||||||
|
@ -445,8 +363,7 @@ namespace GtkSharp.Generation {
|
||||||
if (implementor == null)
|
if (implementor == null)
|
||||||
GenEventHandler (gen_info);
|
GenEventHandler (gen_info);
|
||||||
|
|
||||||
GenCallback (sw);
|
GenDefaultHandlerDelegate (gen_info, implementor);
|
||||||
GenDefaultHandlerDelegate (sw, implementor);
|
|
||||||
GenVirtualMethod (sw, implementor);
|
GenVirtualMethod (sw, implementor);
|
||||||
GenEvent (sw, implementor, "this");
|
GenEvent (sw, implementor, "this");
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ sources = \
|
||||||
SignalArgs.cs \
|
SignalArgs.cs \
|
||||||
SignalAttribute.cs \
|
SignalAttribute.cs \
|
||||||
SignalCallback.cs \
|
SignalCallback.cs \
|
||||||
|
SignalClosure.cs \
|
||||||
SList.cs \
|
SList.cs \
|
||||||
Source.cs \
|
Source.cs \
|
||||||
Spawn.cs \
|
Spawn.cs \
|
||||||
|
|
|
@ -350,7 +350,7 @@ namespace GLib {
|
||||||
|
|
||||||
Hashtable before_signals;
|
Hashtable before_signals;
|
||||||
[Obsolete ("Replaced by GLib.Signal marshaling mechanism.")]
|
[Obsolete ("Replaced by GLib.Signal marshaling mechanism.")]
|
||||||
protected Hashtable BeforeSignals {
|
protected internal Hashtable BeforeSignals {
|
||||||
get {
|
get {
|
||||||
if (before_signals == null)
|
if (before_signals == null)
|
||||||
before_signals = new Hashtable ();
|
before_signals = new Hashtable ();
|
||||||
|
@ -360,7 +360,7 @@ namespace GLib {
|
||||||
|
|
||||||
Hashtable after_signals;
|
Hashtable after_signals;
|
||||||
[Obsolete ("Replaced by GLib.Signal marshaling mechanism.")]
|
[Obsolete ("Replaced by GLib.Signal marshaling mechanism.")]
|
||||||
protected Hashtable AfterSignals {
|
protected internal Hashtable AfterSignals {
|
||||||
get {
|
get {
|
||||||
if (after_signals == null)
|
if (after_signals == null)
|
||||||
after_signals = new Hashtable ();
|
after_signals = new Hashtable ();
|
||||||
|
@ -520,5 +520,12 @@ namespace GLib {
|
||||||
{
|
{
|
||||||
tref.Harden ();
|
tref.Harden ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if false
|
||||||
|
static Object ()
|
||||||
|
{
|
||||||
|
GLib.Log.SetLogHandler ("GLib-GObject", GLib.LogLevelFlags.All, GLib.Log.PrintTraceLogFunction);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
310
glib/Signal.cs
310
glib/Signal.cs
|
@ -31,61 +31,182 @@ namespace GLib {
|
||||||
Swapped = 1 << 1,
|
Swapped = 1 << 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
|
||||||
internal enum SignalFlags {
|
|
||||||
RunFirst = 1 << 0,
|
|
||||||
RunLast = 1 << 1,
|
|
||||||
RunCleanup = 1 << 2,
|
|
||||||
NoRecurse = 1 << 3,
|
|
||||||
Detailed = 1 << 4,
|
|
||||||
Action = 1 << 5,
|
|
||||||
NoHooks = 1 << 6
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout (LayoutKind.Sequential)]
|
|
||||||
internal struct InvocationHint {
|
|
||||||
public uint signal_id;
|
|
||||||
public uint detail;
|
|
||||||
public SignalFlags run_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Signal {
|
public class Signal {
|
||||||
|
|
||||||
GCHandle gc_handle;
|
[Flags]
|
||||||
|
public enum Flags {
|
||||||
|
RunFirst = 1 << 0,
|
||||||
|
RunLast = 1 << 1,
|
||||||
|
RunCleanup = 1 << 2,
|
||||||
|
NoRecurse = 1 << 3,
|
||||||
|
Detailed = 1 << 4,
|
||||||
|
Action = 1 << 5,
|
||||||
|
NoHooks = 1 << 6
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout (LayoutKind.Sequential)]
|
||||||
|
public struct InvocationHint {
|
||||||
|
public uint signal_id;
|
||||||
|
public uint detail;
|
||||||
|
public Flags run_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
[CDeclCallback]
|
||||||
|
public delegate bool EmissionHookNative (ref InvocationHint hint, uint n_pvals, IntPtr pvals, IntPtr data);
|
||||||
|
|
||||||
|
public delegate bool EmissionHook (InvocationHint ihint, object[] inst_and_param_values);
|
||||||
|
|
||||||
|
public class EmissionHookMarshaler {
|
||||||
|
|
||||||
|
EmissionHook handler;
|
||||||
|
EmissionHookNative cb;
|
||||||
|
IntPtr user_data;
|
||||||
|
GCHandle gch;
|
||||||
|
|
||||||
|
public EmissionHookMarshaler (EmissionHook handler)
|
||||||
|
{
|
||||||
|
this.handler = handler;
|
||||||
|
cb = new EmissionHookNative (NativeCallback);
|
||||||
|
gch = GCHandle.Alloc (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmissionHookMarshaler (EmissionHookNative callback, IntPtr user_data)
|
||||||
|
{
|
||||||
|
cb = callback;
|
||||||
|
this.user_data = user_data;
|
||||||
|
handler = new EmissionHook (NativeInvoker);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeCallback (ref InvocationHint hint, uint n_pvals, IntPtr pvals_ptr, IntPtr data)
|
||||||
|
{
|
||||||
|
object[] pvals = new object [n_pvals];
|
||||||
|
for (int i = 0; i < n_pvals; i++) {
|
||||||
|
IntPtr p = new IntPtr ((long) pvals_ptr + i * Marshal.SizeOf (typeof (Value)));
|
||||||
|
Value v = (Value) Marshal.PtrToStructure (p, typeof (Value));
|
||||||
|
pvals [i] = v.Val;
|
||||||
|
}
|
||||||
|
bool result = handler (hint, pvals);
|
||||||
|
if (!result)
|
||||||
|
gch.Free ();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmissionHookNative Callback {
|
||||||
|
get {
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NativeInvoker (InvocationHint ihint, object[] pvals)
|
||||||
|
{
|
||||||
|
int val_sz = Marshal.SizeOf (typeof (Value));
|
||||||
|
IntPtr buf = Marshal.AllocHGlobal (pvals.Length * val_sz);
|
||||||
|
Value[] vals = new Value [pvals.Length];
|
||||||
|
for (int i = 0; i < pvals.Length; i++) {
|
||||||
|
vals [i] = new Value (pvals [i]);
|
||||||
|
IntPtr p = new IntPtr ((long) buf + i * val_sz);
|
||||||
|
Marshal.StructureToPtr (vals [i], p, false);
|
||||||
|
}
|
||||||
|
bool result = cb (ref ihint, (uint) pvals.Length, buf, user_data);
|
||||||
|
foreach (Value v in vals)
|
||||||
|
v.Dispose ();
|
||||||
|
Marshal.FreeHGlobal (buf);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmissionHook Invoker {
|
||||||
|
get {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ToggleRef tref;
|
ToggleRef tref;
|
||||||
string name;
|
string name;
|
||||||
uint before_id = UInt32.MaxValue;
|
Type args_type;
|
||||||
uint after_id = UInt32.MaxValue;
|
SignalClosure before_closure;
|
||||||
Delegate marshaler;
|
SignalClosure after_closure;
|
||||||
|
|
||||||
~Signal ()
|
|
||||||
{
|
|
||||||
gc_handle.Free ();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Signal (GLib.Object obj, string signal_name, Delegate marshaler)
|
private Signal (GLib.Object obj, string signal_name, Delegate marshaler)
|
||||||
{
|
{
|
||||||
tref = obj.ToggleRef;
|
tref = obj.ToggleRef;
|
||||||
name = signal_name;
|
name = signal_name;
|
||||||
this.marshaler = marshaler;
|
tref.Signals [name] = this;
|
||||||
gc_handle = GCHandle.Alloc (this, GCHandleType.Weak);
|
}
|
||||||
|
|
||||||
|
private Signal (GLib.Object obj, string signal_name, Type args_type)
|
||||||
|
{
|
||||||
|
tref = obj.ToggleRef;
|
||||||
|
name = signal_name;
|
||||||
|
this.args_type = args_type;
|
||||||
tref.Signals [name] = this;
|
tref.Signals [name] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void Free ()
|
internal void Free ()
|
||||||
{
|
{
|
||||||
DisconnectHandler (before_id);
|
if (before_closure != null)
|
||||||
DisconnectHandler (after_id);
|
before_closure.Dispose ();
|
||||||
before_handler = after_handler = marshaler = null;
|
if (after_closure != null)
|
||||||
gc_handle.Free ();
|
after_closure.Dispose ();
|
||||||
GC.SuppressFinalize (this);
|
GC.SuppressFinalize (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClosureDisposedCB (object o, EventArgs args)
|
||||||
|
{
|
||||||
|
if (o == before_closure) {
|
||||||
|
before_closure.Disposed -= ClosureDisposedHandler;
|
||||||
|
before_closure.Invoked -= ClosureInvokedCB;
|
||||||
|
if (tref.Target != null)
|
||||||
|
tref.Target.BeforeSignals.Remove (name);
|
||||||
|
before_closure = null;
|
||||||
|
} else {
|
||||||
|
after_closure.Disposed -= ClosureDisposedHandler;
|
||||||
|
after_closure.Invoked -= ClosureInvokedCB;
|
||||||
|
if (tref.Target != null)
|
||||||
|
tref.Target.AfterSignals.Remove (name);
|
||||||
|
after_closure = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (before_closure == null && after_closure == null)
|
||||||
|
tref.Signals.Remove (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventHandler closure_disposed_cb;
|
||||||
|
EventHandler ClosureDisposedHandler {
|
||||||
|
get {
|
||||||
|
if (closure_disposed_cb == null)
|
||||||
|
closure_disposed_cb = new EventHandler (ClosureDisposedCB);
|
||||||
|
return closure_disposed_cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClosureInvokedCB (object o, ClosureInvokedArgs args)
|
||||||
|
{
|
||||||
|
Delegate handler;
|
||||||
|
if (o == before_closure)
|
||||||
|
handler = args.Target.BeforeSignals [name] as Delegate;
|
||||||
|
else
|
||||||
|
handler = args.Target.AfterSignals [name] as Delegate;
|
||||||
|
|
||||||
|
if (handler != null)
|
||||||
|
handler.DynamicInvoke (new object[] {args.Target, args.Args});
|
||||||
|
}
|
||||||
|
|
||||||
|
ClosureInvokedHandler closure_invoked_cb;
|
||||||
|
ClosureInvokedHandler ClosureInvokedHandler {
|
||||||
|
get {
|
||||||
|
if (closure_invoked_cb == null)
|
||||||
|
closure_invoked_cb = new ClosureInvokedHandler (ClosureInvokedCB);
|
||||||
|
return closure_invoked_cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static Signal Lookup (GLib.Object obj, string name)
|
public static Signal Lookup (GLib.Object obj, string name)
|
||||||
{
|
{
|
||||||
return Lookup (obj, name, EventHandlerDelegate);
|
return Lookup (obj, name, typeof (EventArgs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Obsolete ("Replaced by Lookup (Object obj, string name, Type args_type)")]
|
||||||
public static Signal Lookup (GLib.Object obj, string name, Delegate marshaler)
|
public static Signal Lookup (GLib.Object obj, string name, Delegate marshaler)
|
||||||
{
|
{
|
||||||
Signal result = obj.ToggleRef.Signals [name] as Signal;
|
Signal result = obj.ToggleRef.Signals [name] as Signal;
|
||||||
|
@ -94,103 +215,69 @@ namespace GLib {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Delegate before_handler;
|
public static Signal Lookup (GLib.Object obj, string name, Type args_type)
|
||||||
Delegate after_handler;
|
{
|
||||||
|
Signal result = obj.ToggleRef.Signals [name] as Signal;
|
||||||
|
if (result == null)
|
||||||
|
result = new Signal (obj, name, args_type);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Delegate Handler {
|
public Delegate Handler {
|
||||||
get {
|
get {
|
||||||
InvocationHint hint = (InvocationHint) Marshal.PtrToStructure (g_signal_get_invocation_hint (tref.Handle), typeof (InvocationHint));
|
InvocationHint hint = (InvocationHint) Marshal.PtrToStructure (g_signal_get_invocation_hint (tref.Handle), typeof (InvocationHint));
|
||||||
if (hint.run_type == SignalFlags.RunFirst)
|
if (hint.run_type == Flags.RunFirst)
|
||||||
return before_handler;
|
return tref.Target.BeforeSignals [name] as Delegate;
|
||||||
else
|
else
|
||||||
return after_handler;
|
return tref.Target.AfterSignals [name] as Delegate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint Connect (int flags)
|
|
||||||
{
|
|
||||||
IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name);
|
|
||||||
uint id = g_signal_connect_data (tref.Handle, native_name, marshaler, (IntPtr) gc_handle, IntPtr.Zero, flags);
|
|
||||||
GLib.Marshaller.Free (native_name);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AddDelegate (Delegate d)
|
public void AddDelegate (Delegate d)
|
||||||
{
|
{
|
||||||
|
if (args_type == null)
|
||||||
|
args_type = d.Method.GetParameters ()[1].ParameterType;
|
||||||
|
|
||||||
if (d.Method.IsDefined (typeof (ConnectBeforeAttribute), false)) {
|
if (d.Method.IsDefined (typeof (ConnectBeforeAttribute), false)) {
|
||||||
if (before_handler == null) {
|
tref.Target.BeforeSignals [name] = Delegate.Combine (tref.Target.BeforeSignals [name] as Delegate, d);
|
||||||
before_handler = d;
|
if (before_closure == null) {
|
||||||
before_id = Connect (0);
|
before_closure = new SignalClosure (tref.Handle, name, args_type);
|
||||||
} else
|
before_closure.Disposed += ClosureDisposedHandler;
|
||||||
before_handler = Delegate.Combine (before_handler, d);
|
before_closure.Invoked += ClosureInvokedHandler;
|
||||||
|
before_closure.Connect (false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (after_handler == null) {
|
tref.Target.AfterSignals [name] = Delegate.Combine (tref.Target.AfterSignals [name] as Delegate, d);
|
||||||
after_handler = d;
|
if (after_closure == null) {
|
||||||
after_id = Connect (1);
|
after_closure = new SignalClosure (tref.Handle, name, args_type);
|
||||||
} else
|
after_closure.Disposed += ClosureDisposedHandler;
|
||||||
after_handler = Delegate.Combine (after_handler, d);
|
after_closure.Invoked += ClosureInvokedHandler;
|
||||||
|
after_closure.Connect (true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveDelegate (Delegate d)
|
public void RemoveDelegate (Delegate d)
|
||||||
{
|
{
|
||||||
|
if (tref.Target == null)
|
||||||
|
return;
|
||||||
|
|
||||||
if (d.Method.IsDefined (typeof (ConnectBeforeAttribute), false)) {
|
if (d.Method.IsDefined (typeof (ConnectBeforeAttribute), false)) {
|
||||||
before_handler = Delegate.Remove (before_handler, d);
|
tref.Target.BeforeSignals [name] = Delegate.Remove (tref.Target.BeforeSignals [name] as Delegate, d);
|
||||||
if (before_handler == null) {
|
if (tref.Target.BeforeSignals [name] == null && before_closure != null) {
|
||||||
DisconnectHandler (before_id);
|
before_closure.Dispose ();
|
||||||
before_id = UInt32.MaxValue;
|
before_closure = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
after_handler = Delegate.Remove (after_handler, d);
|
tref.Target.AfterSignals [name] = Delegate.Remove (tref.Target.AfterSignals [name] as Delegate, d);
|
||||||
if (after_handler == null) {
|
if (tref.Target.AfterSignals [name] == null && after_closure != null) {
|
||||||
DisconnectHandler (after_id);
|
after_closure.Dispose ();
|
||||||
after_id = UInt32.MaxValue;
|
after_closure = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (after_id == UInt32.MaxValue && before_id == UInt32.MaxValue)
|
|
||||||
tref.Signals.Remove (name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisconnectHandler (uint handler_id)
|
|
||||||
{
|
|
||||||
if (handler_id != UInt32.MaxValue && g_signal_handler_is_connected (tref.Handle, handler_id))
|
|
||||||
g_signal_handler_disconnect (tref.Handle, handler_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
[CDeclCallback]
|
|
||||||
delegate void voidObjectDelegate (IntPtr handle, IntPtr gch);
|
|
||||||
|
|
||||||
static void voidObjectCallback (IntPtr handle, IntPtr data)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (data == IntPtr.Zero)
|
|
||||||
return;
|
|
||||||
GCHandle gch = (GCHandle) data;
|
|
||||||
if (gch.Target == null)
|
|
||||||
return;
|
|
||||||
Signal sig = gch.Target as Signal;
|
|
||||||
if (sig == null) {
|
|
||||||
ExceptionManager.RaiseUnhandledException (new Exception ("Unknown signal class GC handle received."), false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventHandler handler = (EventHandler) sig.Handler;
|
|
||||||
handler (Object.GetObject (handle), EventArgs.Empty);
|
|
||||||
} catch (Exception e) {
|
|
||||||
ExceptionManager.RaiseUnhandledException (e, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static voidObjectDelegate event_handler_delegate;
|
|
||||||
static voidObjectDelegate EventHandlerDelegate {
|
|
||||||
get {
|
|
||||||
if (event_handler_delegate == null)
|
|
||||||
event_handler_delegate = new voidObjectDelegate (voidObjectCallback);
|
|
||||||
return event_handler_delegate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static object Emit (GLib.Object instance, string signal_name, string detail, params object[] args)
|
public static object Emit (GLib.Object instance, string signal_name, string detail, params object[] args)
|
||||||
{
|
{
|
||||||
uint signal_id = GetSignalId (signal_name, instance);
|
uint signal_id = GetSignalId (signal_name, instance);
|
||||||
|
@ -233,18 +320,9 @@ namespace GLib {
|
||||||
return signal_id;
|
return signal_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
[DllImport("libgobject-2.0-0.dll")]
|
|
||||||
static extern uint g_signal_connect_data(IntPtr obj, IntPtr name, Delegate cb, IntPtr gc_handle, IntPtr dummy, int flags);
|
|
||||||
|
|
||||||
[DllImport("libgobject-2.0-0.dll")]
|
[DllImport("libgobject-2.0-0.dll")]
|
||||||
static extern IntPtr g_signal_get_invocation_hint (IntPtr instance);
|
static extern IntPtr g_signal_get_invocation_hint (IntPtr instance);
|
||||||
|
|
||||||
[DllImport("libgobject-2.0-0.dll")]
|
|
||||||
static extern void g_signal_handler_disconnect (IntPtr instance, uint handler);
|
|
||||||
|
|
||||||
[DllImport("libgobject-2.0-0.dll")]
|
|
||||||
static extern bool g_signal_handler_is_connected (IntPtr instance, uint handler);
|
|
||||||
|
|
||||||
[DllImport("libgobject-2.0-0.dll")]
|
[DllImport("libgobject-2.0-0.dll")]
|
||||||
static extern void g_signal_emitv (IntPtr instance_and_params, uint signal_id, uint gquark_detail, ref GLib.Value return_value);
|
static extern void g_signal_emitv (IntPtr instance_and_params, uint signal_id, uint gquark_detail, ref GLib.Value return_value);
|
||||||
|
|
||||||
|
|
188
glib/SignalClosure.cs
Normal file
188
glib/SignalClosure.cs
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
// SignalClosure.cs - signal marshaling class
|
||||||
|
//
|
||||||
|
// Authors: Mike Kestner <mkestner@novell.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2008 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.Collections;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
internal class ClosureInvokedArgs : EventArgs {
|
||||||
|
|
||||||
|
EventArgs args;
|
||||||
|
GLib.Object obj;
|
||||||
|
object result;
|
||||||
|
|
||||||
|
public ClosureInvokedArgs (GLib.Object obj, EventArgs args)
|
||||||
|
{
|
||||||
|
this.obj = obj;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EventArgs Args {
|
||||||
|
get {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GLib.Object Target {
|
||||||
|
get {
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal delegate void ClosureInvokedHandler (object o, ClosureInvokedArgs args);
|
||||||
|
|
||||||
|
internal class SignalClosure : IDisposable {
|
||||||
|
|
||||||
|
IntPtr handle;
|
||||||
|
IntPtr raw_closure;
|
||||||
|
string name;
|
||||||
|
uint id = UInt32.MaxValue;
|
||||||
|
System.Type args_type;
|
||||||
|
|
||||||
|
static Hashtable closures = new Hashtable ();
|
||||||
|
|
||||||
|
public SignalClosure (IntPtr obj, string signal_name, System.Type args_type)
|
||||||
|
{
|
||||||
|
raw_closure = glibsharp_closure_new (Marshaler, Notify, IntPtr.Zero);
|
||||||
|
closures [raw_closure] = this;
|
||||||
|
handle = obj;
|
||||||
|
name = signal_name;
|
||||||
|
this.args_type = args_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler Disposed;
|
||||||
|
public event ClosureInvokedHandler Invoked;
|
||||||
|
|
||||||
|
public void Connect (bool is_after)
|
||||||
|
{
|
||||||
|
IntPtr native_name = GLib.Marshaller.StringToPtrGStrdup (name);
|
||||||
|
id = g_signal_connect_closure (handle, native_name, raw_closure, is_after);
|
||||||
|
GLib.Marshaller.Free (native_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Disconnect ()
|
||||||
|
{
|
||||||
|
if (id != UInt32.MaxValue && g_signal_handler_is_connected (handle, id))
|
||||||
|
g_signal_handler_disconnect (handle, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose ()
|
||||||
|
{
|
||||||
|
Disconnect ();
|
||||||
|
closures.Remove (raw_closure);
|
||||||
|
if (Disposed != null)
|
||||||
|
Disposed (this, EventArgs.Empty);
|
||||||
|
GC.SuppressFinalize (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Invoke (ClosureInvokedArgs args)
|
||||||
|
{
|
||||||
|
if (Invoked == null)
|
||||||
|
return;
|
||||||
|
Invoked (this, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClosureMarshal marshaler;
|
||||||
|
static ClosureMarshal Marshaler {
|
||||||
|
get {
|
||||||
|
if (marshaler == null)
|
||||||
|
marshaler = new ClosureMarshal (MarshalCallback);
|
||||||
|
return marshaler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[CDeclCallback]
|
||||||
|
delegate void ClosureMarshal (IntPtr closure, IntPtr return_val, uint n_param_vals, IntPtr param_values, IntPtr invocation_hint, IntPtr marshal_data);
|
||||||
|
|
||||||
|
static void MarshalCallback (IntPtr raw_closure, IntPtr return_val, uint n_param_vals, IntPtr param_values, IntPtr invocation_hint, IntPtr marshal_data)
|
||||||
|
{
|
||||||
|
string message = String.Empty;
|
||||||
|
|
||||||
|
try {
|
||||||
|
SignalClosure closure = closures [raw_closure] as SignalClosure;
|
||||||
|
message = "Marshaling " + closure.name + " signal";
|
||||||
|
Value objval = (Value) Marshal.PtrToStructure (param_values, typeof (Value));
|
||||||
|
GLib.Object __obj = objval.Val as GLib.Object;
|
||||||
|
if (__obj == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (closure.args_type == typeof (EventArgs)) {
|
||||||
|
closure.Invoke (new ClosureInvokedArgs (__obj, EventArgs.Empty));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SignalArgs args = Activator.CreateInstance (closure.args_type, new object [0]) as SignalArgs;
|
||||||
|
args.Args = new object [n_param_vals - 1];
|
||||||
|
for (int i = 1; i < n_param_vals; i++) {
|
||||||
|
IntPtr ptr = new IntPtr ((long)param_values + i * Marshal.SizeOf (typeof (Value)));
|
||||||
|
Value val = (Value) Marshal.PtrToStructure (ptr, typeof (Value));
|
||||||
|
args.Args [i - 1] = val.Val;
|
||||||
|
}
|
||||||
|
ClosureInvokedArgs ci_args = new ClosureInvokedArgs (__obj, args);
|
||||||
|
closure.Invoke (ci_args);
|
||||||
|
if (return_val == IntPtr.Zero || args.RetVal == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Value ret = (Value) Marshal.PtrToStructure (return_val, typeof (Value));
|
||||||
|
ret.Val = args.RetVal;
|
||||||
|
Marshal.StructureToPtr (ret, return_val, false);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Console.WriteLine (message);
|
||||||
|
ExceptionManager.RaiseUnhandledException (e, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[CDeclCallback]
|
||||||
|
delegate void ClosureNotify (IntPtr data, IntPtr closure);
|
||||||
|
|
||||||
|
static void NotifyCallback (IntPtr data, IntPtr raw_closure)
|
||||||
|
{
|
||||||
|
SignalClosure closure = closures [raw_closure] as SignalClosure;
|
||||||
|
if (closure != null)
|
||||||
|
closure.Dispose ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClosureNotify notify_handler;
|
||||||
|
static ClosureNotify Notify {
|
||||||
|
get {
|
||||||
|
if (notify_handler == null)
|
||||||
|
notify_handler = new ClosureNotify (NotifyCallback);
|
||||||
|
return notify_handler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("glibsharpglue-2")]
|
||||||
|
static extern IntPtr glibsharp_closure_new (ClosureMarshal marshaler, ClosureNotify notify, IntPtr gch);
|
||||||
|
|
||||||
|
[DllImport("libgobject-2.0-0.dll")]
|
||||||
|
static extern uint g_signal_connect_closure (IntPtr obj, IntPtr name, IntPtr closure, bool is_after);
|
||||||
|
|
||||||
|
[DllImport("libgobject-2.0-0.dll")]
|
||||||
|
static extern void g_signal_handler_disconnect (IntPtr instance, uint handler);
|
||||||
|
|
||||||
|
[DllImport("libgobject-2.0-0.dll")]
|
||||||
|
static extern bool g_signal_handler_is_connected (IntPtr instance, uint handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -69,7 +69,9 @@ namespace GLib {
|
||||||
|
|
||||||
public GLib.Object Target {
|
public GLib.Object Target {
|
||||||
get {
|
get {
|
||||||
if (reference is GLib.Object)
|
if (reference == null)
|
||||||
|
return null;
|
||||||
|
else if (reference is GLib.Object)
|
||||||
return reference as GLib.Object;
|
return reference as GLib.Object;
|
||||||
|
|
||||||
WeakReference weak = reference as WeakReference;
|
WeakReference weak = reference as WeakReference;
|
||||||
|
@ -77,11 +79,12 @@ namespace GLib {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Free ()
|
public void Free ()
|
||||||
{
|
{
|
||||||
foreach (Signal s in Signals.Values)
|
Signal[] signals = new Signal [Signals.Count];
|
||||||
|
Signals.Values.CopyTo (signals, 0);
|
||||||
|
foreach (Signal s in signals)
|
||||||
s.Free ();
|
s.Free ();
|
||||||
Signals.Clear ();
|
|
||||||
if (hardened)
|
if (hardened)
|
||||||
g_object_unref (handle);
|
g_object_unref (handle);
|
||||||
else
|
else
|
||||||
|
|
|
@ -3,6 +3,7 @@ lib_LTLIBRARIES = libglibsharpglue-2.la
|
||||||
libglibsharpglue_2_la_LDFLAGS = -module -avoid-version -no-undefined
|
libglibsharpglue_2_la_LDFLAGS = -module -avoid-version -no-undefined
|
||||||
|
|
||||||
libglibsharpglue_2_la_SOURCES = \
|
libglibsharpglue_2_la_SOURCES = \
|
||||||
|
closure.c \
|
||||||
error.c \
|
error.c \
|
||||||
list.c \
|
list.c \
|
||||||
object.c \
|
object.c \
|
||||||
|
|
35
glib/glue/closure.c
Normal file
35
glib/glue/closure.c
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/* closure.c : Native closure implementation
|
||||||
|
*
|
||||||
|
* Author: Mike Kestner <mkestner@novell.com>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2008 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 <glib-object.h>
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
GClosure* glibsharp_closure_new (GClosureMarshal marshaler, GClosureNotify notify, gpointer data);
|
||||||
|
/* */
|
||||||
|
|
||||||
|
GClosure*
|
||||||
|
glibsharp_closure_new (GClosureMarshal marshaler, GClosureNotify notify, gpointer data)
|
||||||
|
{
|
||||||
|
GClosure *closure = g_closure_new_simple (sizeof (GClosure), data);
|
||||||
|
g_closure_set_marshal (closure, marshaler);
|
||||||
|
g_closure_add_finalize_notifier (closure, data, notify);
|
||||||
|
return closure;
|
||||||
|
}
|
Loading…
Reference in a new issue