2004-12-11 Alp Toker <alp@atoker.com>
authorAlp Toker <alp@mono-cvs.ximian.com>
Sat, 11 Dec 2004 20:50:55 +0000 (20:50 -0000)
committerAlp Toker <alp@mono-cvs.ximian.com>
Sat, 11 Dec 2004 20:50:55 +0000 (20:50 -0000)
  * cilc.cs:
  First stab at initialising delegates using method pointers.
  Convert the type registry management and reporting methods to use strings,
  making way for tie-in with native GObject hierarchies.
  Recursive conflict avoidance for the GObject class struct etc.
  Treat byref values properly.
  Support tie-in with existing GObject hierarchy.
  Use argc parity to decide the generation mode.
  Update usage help string.
  * res-Makefile:
  Use passed CFLAGS.
  Only rebuild modified targets if bundle is defined, not everything.
  * README:
  More usage examples.

svn path=/trunk/mcs/; revision=37638

mcs/tools/cilc/ChangeLog
mcs/tools/cilc/README
mcs/tools/cilc/cilc.cs
mcs/tools/cilc/res-Makefile

index f988af2d92e4dc6c57b25f3d2dc4c8abcb033db4..f5d2aa57c06abd04fbbbd8c506f37c32c56f5229 100644 (file)
@@ -1,3 +1,20 @@
+2004-12-11  Alp Toker  <alp@atoker.com>
+
+       * cilc.cs:
+       First stab at initialising delegates using method pointers.
+       Convert the type registry management and reporting methods to use strings,
+       making way for tie-in with native GObject hierarchies.
+       Recursive conflict avoidance for the GObject class struct etc.
+       Treat byref values properly.
+       Support tie-in with existing GObject hierarchy.
+       Use argc parity to decide the generation mode.
+       Update usage help string.
+       * res-Makefile:
+       Use passed CFLAGS.
+       Only rebuild modified targets if bundle is defined, not everything.
+       * README:
+       More usage examples.
+
 2004-12-10  Alp Toker  <alp@atoker.com>
 
   * cilc.cs:
index d30fd43d54bb37d9302dd4b8e962a7af86fc190c..a40bdc74e61b002a009f28d9a97659b26449b933 100644 (file)
@@ -36,5 +36,18 @@ generate bindings in a temporary directory, compile them using the bundle
 feature, and install the produced shared library in the lib/ subdirectory and
 the headers in include/.
 
+$ cilc Assembly.dll
+
+To tie-in with existing GOjbect hierarchies, pass pairs of pkg-config package
+and comma-separated namespaces. For example:
+
+If you want to use a Gtk# widget in a Gtk+ application:
+
+$ cilc Widget.dll gtk+-2.0 gtk
+
+To bind gtk-sharp, but tying it into the native hierarchy for gdk:
+
+$ cilc gtk-sharp.dll gtk+-2.0 gdk
+
 -- 
 Alp Toker <alp@atoker.com>
index 8c9368041c4e3096d252aee80d1725cf38636a2b..32983b6df4dc4482e43fbf59583454f1459b1b0b 100644 (file)
@@ -7,6 +7,7 @@ using System.IO;
 using System.Reflection;
 using System.Collections;
 using System.Diagnostics;
+using System.Text.RegularExpressions;
 
 public class cilc
 {
@@ -14,45 +15,73 @@ public class cilc
 
        static CodeWriter C, H, Cindex, Hindex, Hdecls;
        static string ns, dllname;
-       static string cur_type, CurType;
+       static string cur_type, CurType, CurTypeClass;
        static string target_dir;
 
        static ArrayList funcs_done = new ArrayList ();
 
        public static int Main (string[] args)
        {
-               if (args.Length < 1 || args.Length > 2) {
+               if (args.Length < 1 || args.Length > 4) {
                        Console.WriteLine ("Mono CIL-to-C binding generator");
-                       Console.WriteLine ("Usage: cilc [options] assembly target");
+                       Console.WriteLine ("Usage: cilc assembly [target] [pkg ns[,ns...]]");
                        return 1;
                }
 
                ns = "Unnamed";
 
-               //by default, generate in temporary directory and invoke make
                if (args.Length == 1) {
-                       //Generate (args[0], Path.GetFileNameWithoutExtension (args[0]));
-                       string tmpdir = Path.GetTempPath () + Path.GetTempFileName ();
-                       string cwd = Directory.GetCurrentDirectory ();
-                       if (Directory.Exists (tmpdir) || File.Exists (tmpdir)) {
-                               Console.WriteLine ("Error: Temporary directory " + tmpdir + " already exists.");
-                               return 1;
-                       }
-                       Generate (args[0], tmpdir);
-                       Console.Write ("Compiling unmanaged binding");
-                       Run ("make", "-C \"" + tmpdir + "\" bundle=true");
-                       Console.WriteLine ();
-                       Console.Write ("Installing to current directory");
-                       Run ("make", "-C \"" + tmpdir + "\" install prefix=\"" + cwd + "\"");
-                       Directory.Delete (tmpdir, true);
-                       Console.WriteLine ();
-               } else
+                       SmartBind (args[0]);
+               } else if (args.Length == 2) {
                        Generate (args[0], args[1]);
+               } else if (args.Length == 3) {
+                       RegisterPkg (args[1], args[2]);
+                       SmartBind (args[0]);
+               } else if (args.Length == 4) {
+                       RegisterPkg (args[2], args[3]);
+                       Generate (args[0], args[1]);
+               }
 
                return 0;
        }
 
-       public static void Run (string cmd, string args)
+
+       public static void SmartBind (string aname)
+       {
+               string tmpdir = Path.GetTempPath () + Path.GetTempFileName ();
+               string cwd = Directory.GetCurrentDirectory ();
+               if (Directory.Exists (tmpdir) || File.Exists (tmpdir)) {
+                       Console.WriteLine ("Error: Temporary directory " + tmpdir + " already exists.");
+                       return;
+               }
+               Generate (aname, tmpdir);
+               Console.Write ("Compiling unmanaged binding");
+               RunWithReport ("make", "-C \"" + tmpdir + "\" bundle=true");
+               Console.WriteLine ();
+               Console.Write ("Installing to current directory");
+               RunWithReport ("make", "-C \"" + tmpdir + "\" install prefix=\"" + cwd + "\"");
+               Directory.Delete (tmpdir, true);
+               Console.WriteLine ();
+       }
+
+       public static string Run (string cmd, string args)
+       {
+               ProcessStartInfo psi = new ProcessStartInfo (cmd, args);
+               psi.UseShellExecute = false;
+               psi.RedirectStandardInput = true;
+               psi.RedirectStandardOutput = true;
+               psi.RedirectStandardError = true;
+
+               Process p = Process.Start (psi);
+
+               string line = p.StandardOutput.ReadLine ();
+
+               p.WaitForExit ();
+
+               return line;
+       }
+
+       public static int RunWithReport (string cmd, string args)
        {
                ProcessStartInfo psi = new ProcessStartInfo (cmd, args);
                psi.UseShellExecute = false;
@@ -68,6 +97,96 @@ public class cilc
                Console.WriteLine ();
 
                Console.Write (p.StandardError.ReadToEnd ());
+
+               p.WaitForExit ();
+
+               return p.ExitCode;
+       }
+
+       static string cflags;
+       static string extpkgs = "";
+       static string[] extsubpkgs = {};
+       static string[] extincludes = {};
+
+       public static void RegisterPkg (string pkg, string subpkgs)
+       {
+               extpkgs += " " + pkg;
+
+               string cflags = Run ("pkg-config", "--cflags-only-I " + pkg);
+
+               extsubpkgs = subpkgs.Trim ().Split (',');
+               extincludes = new string[extsubpkgs.Length];
+
+               for (int i = 0 ; i != extsubpkgs.Length ; i++)
+                       extincludes[i] =  extsubpkgs[i] + "/" + extsubpkgs[i] + ".h";
+
+               //string cmd = "gcc";
+               //string args = "-E " + cflags + " " + includedir + "/" + hname;
+
+               string cppincludes = "";
+               foreach (string include in extincludes)
+                       cppincludes += " -include " + include;
+
+               string cmd = "cpp";
+               string args = cflags + cppincludes + " /dev/null";
+
+               ProcessStartInfo psi = new ProcessStartInfo (cmd, args);
+               psi.UseShellExecute = false;
+               psi.RedirectStandardOutput = true;
+               psi.RedirectStandardError = true;
+
+               Process p = Process.Start (psi);
+
+               string line;
+
+               Regex re_type = new Regex (@"typedef struct (_\w+) (\w+);");
+               Regex re_enum = new Regex (@"} (\w+);");
+
+               while ((line = p.StandardOutput.ReadLine ()) != null) {
+                       line = line.Trim ();
+
+                       Match m;
+
+                       m = re_type.Match (line);
+                       if (m.Success) {
+                               string G = m.Groups[2].Value;
+
+                               bool dontgen = false;
+
+                               if (!GIsValid (G))
+                                       continue;
+
+                               if (G.EndsWith ("Class"))
+                                       continue;
+
+                               RegisterG (G);
+                               continue;
+                       }
+
+                       m = re_enum.Match (line);
+                       if (m.Success) {
+                               string G = m.Groups[1].Value;
+
+                               if (!GIsValid (G))
+                                       continue;
+
+                               RegisterG (G);
+                               RegisterByVal (G);
+                               continue;
+                       }
+               }
+
+               p.WaitForExit ();
+               Console.Write (p.StandardError.ReadToEnd ());
+               Console.WriteLine ();
+       }
+
+       static bool GIsValid (string G) {
+               foreach (string extsubpkg in extsubpkgs)
+                       if (G.ToLower ().StartsWith (extsubpkg))
+                               return true;
+
+               return false;
        }
 
        public static void Generate (string assembly, string target)
@@ -81,21 +200,12 @@ public class cilc
 
                Directory.CreateDirectory (target_dir);
 
-               //register handled primitive types
-               //TODO: sync these with the handled types
-               RegisterCsType (typeof (string));
-               RegisterCsType (typeof (int));
-               RegisterCsType (typeof (bool));
-               RegisterCsType (typeof (IntPtr));
-               
-               //TODO: parse given .h files here and register the type names
-
                Assembly a = Assembly.LoadFrom (assembly);
 
                Console.WriteLine ();
                Console.WriteLine ("References (not followed):");
                foreach (AssemblyName reference in a.GetReferencedAssemblies ())
-               Console.WriteLine ("  " + reference.Name);
+                       Console.WriteLine ("  " + reference.Name);
                Console.WriteLine ();
 
                dllname = Path.GetFileName (assembly);
@@ -120,21 +230,26 @@ public class cilc
                makefile_defs.WriteLine ("ASSEMBLY = " + assembly);
                makefile_defs.WriteLine ("SONAME = " + soname);
                makefile_defs.WriteLine (@"OBJS = $(shell ls *.c | sed -e 's/\.c/.o/')");
+
+               if (extpkgs != "") {
+                       makefile_defs.WriteLine ("EXTRAINCLUDES = $(shell pkg-config --cflags" + extpkgs + ")");
+                       makefile_defs.WriteLine ("EXTRALIBS = $(shell pkg-config --libs" + extpkgs + ")");
+               }
                makefile_defs.Close ();
 
                Console.WriteLine ();
 
                //identify hits on types that were registered too late
-               foreach (Type rtype in registered_types) {
-                       string tname = rtype.FullName + " (type)";
-                       if (registry_hits.Contains (tname)) {
-                               Console.WriteLine ("Warning: " + tname + " was incorrectly registered after it was needed instead of before. Consider re-ordering.");
+               foreach (string tn in registered_types) {
+                       if (registry_hits.Contains (tn)) {
+                               Console.WriteLine ("Warning: " + tn + " was incorrectly registered after it was needed instead of before. Consider re-ordering.");
                        }
                }
 
                MakeReport (registry_hits, "Type registry missed hits", 20);
                Console.WriteLine ();
-               Console.WriteLine (registered_types.Count + " types generated in " + namespaces.Length + " namespaces; " + warnings_ignored + " types ignored");
+               //TODO: this count is now wrong
+               Console.WriteLine (registered_types.Count + " types generated/seen in " + namespaces.Length + " namespaces; " + warnings_ignored + " types ignored");
                Console.WriteLine ();
        }
 
@@ -173,7 +288,10 @@ public class cilc
                                continue;
                        }
 
-                       RegisterCsType (t);
+                       RegisterType (t);
+
+                       if (t.IsEnum)
+                               RegisterByVal (t);
 
                        if (!ns_types.Contains (t.Namespace))
                                ns_types[t.Namespace] = new ArrayList ();
@@ -193,9 +311,9 @@ public class cilc
        {
                //ns = types[0].Namespace;
                ns = given_ns;
-               
+
                Hindex = new CodeWriter (target_dir + NsToFlat (ns).ToLower () + ".h");
-               Hdecls = new CodeWriter (target_dir + NsToFlat (ns).ToLower () + "-decls.h");
+               Hdecls = new CodeWriter (target_dir + NsToFlat (ns).ToLower () + "types.h");
                Cindex = new CodeWriter (target_dir + NsToFlat (ns).ToLower () + ".c");
 
                string Hindex_id = "__" + NsToFlat (ns).ToUpper () + "_H__";
@@ -251,7 +369,7 @@ public class cilc
 
                Hindex.WriteLine ();
                Hindex.WriteLine ("#endif /* " + Hindex_id + " */");
-               
+
                Hdecls.WriteLine ();
                Hdecls.WriteLine ("#endif /* " + Hdecls_id + " */");
 
@@ -264,14 +382,16 @@ public class cilc
        {
                //TODO: we only handle ordinary classes for now
                /*
-                 else if (t.IsSubclassOf (typeof (Delegate))) {
-                       Console.WriteLine ("Ignoring delegate: " + t.Name);
-                       return;
-               }
-               */
+                        else if (t.IsSubclassOf (typeof (Delegate))) {
+                        Console.WriteLine ("Ignoring delegate: " + t.Name);
+                        return;
+                        }
+                        */
 
                cur_type = NsToC (ns) + "_" + CamelToC (t.Name);
-               CurType = NsToFlat (ns) + t.Name;
+               //CurType = NsToFlat (ns) + t.Name;
+               CurType = CsTypeToG (t);
+               CurTypeClass = GToGC (CurType);
 
                //ns = t.Namespace;
                string fname = NsToFlat (ns).ToLower () + t.Name.ToLower ();
@@ -287,13 +407,17 @@ public class cilc
 
                H.WriteLine ("#include <glib.h>");
                H.WriteLine ("#include <glib-object.h>");
+
+               foreach (string include in extincludes)
+                       H.WriteLine ("#include <" + include + ">");
+
                H.WriteLine ();
-               
+
                if (IsRegistered (t.BaseType))
                        H.WriteLine ("#include \"" + NsToFlat (t.BaseType.Namespace).ToLower () + t.BaseType.Name.ToLower () + ".h\"");
 
                foreach (string ext_ns in namespaces)
-                       H.WriteLine ("#include \"" + NsToFlat (ext_ns).ToLower () + "-decls.h\"");
+                       H.WriteLine ("#include \"" + NsToFlat (ext_ns).ToLower () + "types.h\"");
 
                H.WriteLine ();
 
@@ -364,7 +488,7 @@ public class cilc
 
                H.WriteLine ("G_BEGIN_DECLS");
                H.WriteLine ();
-               
+
                {
                        string NS = NsToC (ns).ToUpper ();
                        string T = CamelToC (t.Name).ToUpper ();
@@ -373,21 +497,21 @@ public class cilc
 
                        H.WriteLine ("#define " + NSTT + " (" + cur_type + "_get_type ())");
                        H.WriteLine ("#define " + NST + "(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), " + NSTT + ", " + CurType + "))");
-                       H.WriteLine ("#define " + NST + "_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), " + NSTT + ", " + CurType + "Class))");
+                       H.WriteLine ("#define " + NST + "_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), " + NSTT + ", " + CurTypeClass + "))");
                        H.WriteLine ("#define " + NS + "_IS_" + T + "(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), " + NSTT + "))");
                        H.WriteLine ("#define " + NS + "_IS_" + T + "_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), " + NSTT + "))");
-                       H.WriteLine ("#define " + NST + "_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), " + NSTT + ", " + CurType + "Class))");
+                       H.WriteLine ("#define " + NST + "_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), " + NSTT + ", " + CurTypeClass + "))");
                }
-               
+
                if (!C.IsDuplicate) {
                        Hdecls.WriteLine ("typedef struct _" + CurType + " " + CurType + ";");
-                       Hdecls.WriteLine ("typedef struct _" + CurType + "Class " + CurType + "Class;");
+                       Hdecls.WriteLine ("typedef struct _" + CurTypeClass + " " + CurTypeClass + ";");
                        Hdecls.WriteLine ();
                }
 
                H.WriteLine ();
                //H.WriteLine ("typedef struct _" + CurType + " " + CurType + ";");
-               
+
                //H.WriteLine ();
                //H.WriteLine ("typedef struct _" + CurType + "Class " + CurType + "Class;");
                H.WriteLine ("typedef struct _" + CurType + "Private " + CurType + "Private;");
@@ -396,20 +520,21 @@ public class cilc
                H.WriteLine ("{");
 
                string ParentName = CsTypeToG (t.BaseType);
+               string ParentNameClass = GToGC (ParentName);
 
                H.WriteLine (ParentName + " parent_instance;");
                H.WriteLine (CurType + "Private *priv;");
                H.WriteLine ("};");
                H.WriteLine ();
-               H.WriteLine ("struct _" + CurType + "Class");
+               H.WriteLine ("struct _" + CurTypeClass);
                H.WriteLine ("{");
-               H.WriteLine (ParentName + "Class parent_class;" + " /* inherits " + t.BaseType.Namespace + " " + t.BaseType.Name + " */");
+               H.WriteLine (ParentNameClass + " parent_class;" + " /* inherits " + t.BaseType.Namespace + " " + t.BaseType.Name + " */");
                H.WriteLine ();
-               
+
                //TODO: event arguments
                foreach (EventInfo ei in events)
                        H.WriteLine ("void (* " + CamelToC (ei.Name) + ") (" + CurType + " *thiz" + ");");
-               
+
                H.WriteLine ("};");
                H.WriteLine ();
 
@@ -438,7 +563,7 @@ public class cilc
 
                //TODO: if the class inherits a known GLib Object, use its raw handle
                C.WriteLine ("static gpointer parent_class;");
-               
+
                if (events.Length == 0)
                        C.WriteLine ("static guint signals[0];");
                else
@@ -469,10 +594,10 @@ public class cilc
                C.WriteLine ("}");
 
                C.WriteLine ();
-       
-               
+
+
                //generate the GObject class init function
-               C.WriteLine ("static void " + cur_type + "_class_init (" + CurType + "Class *klass" + ")");
+               C.WriteLine ("static void " + cur_type + "_class_init (" + CurTypeClass + " *klass" + ")");
                C.WriteLine ("{");
 
                C.WriteLine ("GObjectClass *object_class = G_OBJECT_CLASS (klass);");
@@ -481,9 +606,9 @@ public class cilc
 
                foreach (EventInfo ei in events)
                        EventGen (ei, t);
-               
+
                C.WriteLine ("}");
-               
+
                C.WriteLine ();
 
 
@@ -497,7 +622,7 @@ public class cilc
                C.WriteLine ();
                C.WriteLine ("static const GTypeInfo object_info =");
                C.WriteLine ("{");
-               C.WriteLine ("sizeof (" + CurType + "Class),");
+               C.WriteLine ("sizeof (" + CurTypeClass + "),");
                C.WriteLine ("(GBaseInitFunc) NULL,");
                C.WriteLine ("(GBaseFinalizeFunc) NULL,");
                C.WriteLine ("(GClassInitFunc) " + cur_type + "_class_init,");
@@ -508,9 +633,9 @@ public class cilc
                C.WriteLine ("(GInstanceInitFunc) " + cur_type + "_init,");
                C.WriteLine ("};");
                C.WriteLine ();
-               
+
                string parent_type = "G_TYPE_OBJECT";
-               if (IsRegistered (t.BaseType))
+               if (IsRegistered (t.BaseType))
                        parent_type = NsToC (t.BaseType.Namespace).ToUpper () + "_TYPE_" + CamelToC (t.BaseType.Name).ToUpper ();
 
                C.WriteLine ("object_type = g_type_register_static (" + parent_type + ", \"" + CurType + "\", &object_info, 0);");
@@ -535,15 +660,38 @@ public class cilc
                methods = t.GetMethods (BindingFlags.Public|BindingFlags.Instance|BindingFlags.DeclaredOnly);
                foreach (MethodInfo m in methods)
                        MethodGen (m, t);
-       
+
                H.WriteLine ();
                H.WriteLine ("G_END_DECLS");
        }
 
-       //FIXME: this won't work in the general case. arraylist should contain just type names, not Types
+       //FIXME: clean up this mess with hits as the type registry uses strings
+
        static ArrayList registered_types = new ArrayList ();
+       static ArrayList registered_byvals = new ArrayList ();
        static Hashtable registry_hits = new Hashtable ();
 
+       static bool IsRegisteredByVal (Type t)
+       {
+               return registered_byvals.Contains (CsTypeToFlat (t));
+       }
+
+       static void RegisterByVal (string tn)
+       {
+               //TODO: warn on dupes
+               registered_byvals.Add (tn);
+       }
+
+       static void RegisterByVal (Type t)
+       {
+               RegisterByVal (CsTypeToFlat (t));
+       }
+
+       static bool IsRegistered (String tn)
+       {
+               return registered_types.Contains (tn);
+       }
+
        static bool IsRegistered (Type t)
        {
                return IsRegistered (t, true);
@@ -551,45 +699,94 @@ public class cilc
 
        static bool IsRegistered (Type t, bool log_hits)
        {
-               bool isreg = registered_types.Contains (t);
+               return IsRegistered (CsTypeToFlat (t), true);
+       }
 
-               if (!isreg && log_hits) {
-                       if (t.Namespace != null && t.Namespace != "")
-                               HitRegistry (t.Namespace + " (namespace)");
+       static bool IsRegistered (string tn, bool log_hits)
+       {
+               //bool isreg = registered_types.Contains (t);
+               bool isreg = registered_types.Contains (tn);
 
-                       HitRegistry (t.FullName + " (type)");
+               if (!isreg && log_hits) {
+                       HitRegistry (tn);
                }
 
                return isreg;
        }
-       
-       static void HitRegistry (string tns)
+
+       static void HitRegistry (string tn)
        {
-               if (!registry_hits.Contains (tns)) {
+               //FIXME: ignore handled primitive types here
+
+               if (!registry_hits.Contains (tn)) {
                        int count = 0;
-                       registry_hits[tns] = count;
+                       registry_hits[tn] = count;
                }
 
-               registry_hits[tns] = (int) registry_hits[tns] + 1;
+               registry_hits[tn] = (int) registry_hits[tn] + 1;
        }
 
-       static void RegisterCsType (Type t)
+       static bool RegisterG (string G)
        {
-               //if (t.IsPrimitive || IsRegistered (t))
-               if (IsRegistered (t, false))
-                       return;
+               if (IsRegistered (G, false)) {
+                       Console.WriteLine ("Warning: unmanaged type " + G + " already registered! Can't re-register.");
+                       return false;
+               }
+
+               registered_types.Add (G);
+               return true;
+       }
+
+       static string NewG (string G)
+       {
+               if (IsRegistered (G, false))
+               {
+                       Console.WriteLine ("Warning: type " + G + " already registered! Appending 'Extra' and trying again");
+                       Console.WriteLine ();
+                       return NewG (G + "Extra"); //FIXME: handle this properly
+               }
 
-               registered_types.Add (t);
+               registered_types.Add (G);
+               return (G);
+       }
+
+       static string CsTypeToFlat (Type t) //TODO: use this everywhere
+       {
+               //TODO: check registry to see if t.Name's name has been changed during NewG.
+               //if it's not in the registry, continue as usual
+
+               return NsToFlat (t.Namespace) + t.Name;
+       }
+
+       static void RegisterType (Type t)
+       {
+               NewG (CsTypeToFlat (t));
+       }
+
+       static string NewG (Type t)
+       {
+               return NewG (CsTypeToFlat (t));
        }
 
        static string CsTypeToG (Type t)
        {
                if (IsRegistered (t))
-                       return NsToFlat (t.Namespace) + t.Name;
+                       return CsTypeToFlat (t);
 
                return "GObject";
        }
 
+       //static string CsTypeToGC (String tn)
+       static string GToGC (string G)
+       {
+               string possGC = G + "Class";
+
+               if (IsRegistered (possGC))
+                       return GToGC (G + "Object");
+               else
+                       return possGC;
+       }
+
        static string CsTypeToC (Type t)
        {
                //TODO: use this method everywhere
@@ -602,6 +799,9 @@ public class cilc
                        case "System.Int32":
                                return "gint ";
 
+                       case "System.UInt32":
+                               return "guint ";
+
                        case "System.Boolean":
                                return "gboolean ";
 
@@ -610,10 +810,13 @@ public class cilc
 
                        //questionable
                        case "System.EventHandler":
-                       case "System.MulticastDelegate":
+                               case "System.MulticastDelegate":
                                return "GCallback ";
                }
 
+               if (IsRegisteredByVal (t))
+                       return CsTypeToFlat (t) + " ";
+
                return CsTypeToG (t) + " *";
        }
 
@@ -628,7 +831,7 @@ public class cilc
                C.WriteLine ("\"" + name + "\",");
                C.WriteLine ("G_OBJECT_CLASS_TYPE (object_class),");
                C.WriteLine ("G_SIGNAL_RUN_LAST,");
-               C.WriteLine ("G_STRUCT_OFFSET (" + CurType + "Class" + ", " + name + "),");
+               C.WriteLine ("G_STRUCT_OFFSET (" + CurTypeClass + ", " + name + "),");
                C.WriteLine ("NULL, NULL,");
                C.WriteLine ("g_cclosure_marshal_VOID__VOID,");
                C.WriteLine ("G_TYPE_NONE, 0");
@@ -659,7 +862,7 @@ public class cilc
                        case "get_type":
                                return "retrieve_type";
                        default:
-                               return name;
+                       return name;
                }
        }
 
@@ -678,20 +881,20 @@ public class cilc
                else {
                        stat = m.IsStatic;
                }
-               
+
                inst = !stat;
 
                string mytype;
                mytype = CurType + " *";
 
                /*
-                  Console.WriteLine (ret_type);
-                  if (ret_type != null && ret_type != typeof (Void)) {
-                  has_return = true;
+                        Console.WriteLine (ret_type);
+                        if (ret_type != null && ret_type != typeof (Void)) {
+                        has_return = true;
                //TODO: return simple gint or gchar if possible
                mytype = "MonoObject *";
                }
-                */
+               */
 
                string params_arg = "NULL";
                if (parameters.Length != 0)
@@ -716,7 +919,7 @@ public class cilc
 
                //handle overloaded methods
                //TODO: generate an alias function for the default ctor etc.
-               
+
                //TODO: how do we choose the default ctor/method overload? perhaps the
                //first/shortest, but we need scope for this
                //perhaps use DefaultMemberAttribute, Type.GetDefaultMembers
@@ -738,7 +941,7 @@ public class cilc
                        return;
 
                funcs_done.Add (myname);
-               
+
                //handle the parameters
                string param_assign = "";
                string mycsargs = "";
@@ -776,11 +979,11 @@ public class cilc
 
                C.WriteLine ("if (_mono_method == NULL) {");
 
-               //if (ctor) C.WriteLine ("MonoMethodDesc *_mono_method_desc = mono_method_desc_new (\":.ctor()\", FALSE);");
-               if (ctor) C.WriteLine ("MonoMethodDesc *_mono_method_desc = mono_method_desc_new (\":.ctor(" + mycsargs + ")\", FALSE);");
-               else {
+               if (ctor)
+                       C.WriteLine ("MonoMethodDesc *_mono_method_desc = mono_method_desc_new (\":.ctor(" + mycsargs + ")\", FALSE);");
+               else
                        C.WriteLine ("MonoMethodDesc *_mono_method_desc = mono_method_desc_new (\":" + m.Name + "(" + mycsargs + ")" + "\", FALSE);");
-               }
+
 
                C.WriteLine ("_mono_method = mono_method_desc_search_in_class (_mono_method_desc, " + cur_type + "_get_mono_class ());");
 
@@ -796,12 +999,17 @@ public class cilc
 
                if (ctor) C.WriteLine (instance_arg + " = (MonoObject*) mono_object_new ((MonoDomain*) " + NsToC (ns) + "_get_mono_domain ()" + ", " + cur_type + "_get_mono_class ());");
 
-               //invoke the method
-               
-               if (ctor || inst)
-                       C.WriteLine ("mono_runtime_invoke (_mono_method, " + instance_arg + ", " + params_arg + ", NULL);");
-               else
-                       C.WriteLine ("mono_runtime_invoke (_mono_method, " + "NULL" + ", " + params_arg + ", NULL);");
+               //delegates are a special case as we want their constructor to take a function pointer
+               if (ctor && t.IsSubclassOf (typeof (MulticastDelegate))) {
+                       C.WriteLine ("mono_delegate_ctor (" + instance_arg + ", object, method);");
+               } else {
+                       //invoke the method
+
+                       if (ctor || inst)
+                               C.WriteLine ("mono_runtime_invoke (_mono_method, " + instance_arg + ", " + params_arg + ", NULL);");
+                       else
+                               C.WriteLine ("mono_runtime_invoke (_mono_method, " + "NULL" + ", " + params_arg + ", NULL);");
+               }
 
                if (ctor) C.WriteLine ("return " + instance + ";");
 
index 181eec9d217784e55d5409fd435fa75859c6bb30..27edfceff984eda1e8e8c62bbc7b2af2179dc2b4 100644 (file)
@@ -1,11 +1,10 @@
 include defs.mk
 
-#LIBNAME = $(basename $(SONAME))
 LIBNAME = $(shell echo $(basename $(SONAME)) | sed -e 's/^lib//')
 HTARGET = $(prefix)/include/$(LIBNAME)/
 LIBTARGET = $(prefix)/lib/
 
-CFLAGS = -static -fpic $(shell pkg-config --cflags glib-2.0 gobject-2.0 mono) -I.
+CFLAGS += -static -fpic $(shell pkg-config --cflags glib-2.0 gobject-2.0 mono) $(EXTRAINCLUDES) -I.
 
 ifdef bundle
 EXTRAOBJS = bundle.o
@@ -20,9 +19,9 @@ endif
 all: $(SONAME)
 
 $(SONAME): $(EXTRAOBJS) $(OBJS)
-       gcc -Wall -fpic -shared `pkg-config --libs glib-2.0 gobject-2.0 mono` -lpthread $(EXTRAOBJS) $(OBJS) -o $(SONAME)
+       gcc -Wall -fpic -shared `pkg-config --libs glib-2.0 gobject-2.0 mono` -lpthread $(EXTRAOBJS) $(OBJS) $(EXTRALIBS) -o $(SONAME)
 
-$(OBJS): $(EXTRATARGETS)
+$(LIBNAME).o: $(EXTRATARGETS)
 
 bundle.o bundle.h: $(ASSEMBLY)
        mkbundle -c -o bundle.c.tmp -oo bundle.o $(ASSEMBLY)