예제 #1
0
        public static GLParser FromFile(string xmlFile, params string[] Api)
        {
            XDocument file = XDocument.Load(xmlFile);
            GLParser  spec = new GLParser();

            spec.HeaderComment = file.Root.Element("comment").Value;

            foreach (var feature in file.Root.Elements("feature"))
            {
                var apiName = feature.Attribute("api").Value;
                if (Api.Contains(apiName))
                {
                    var version = new GLVersion
                    {
                        Api    = feature.Attribute("api").Value.ToUpper(),
                        Number = feature.Attribute("number").Value,
                    };

                    version.Name = version.Api + version.Number.Replace(".", "");

                    // Add all enums and commands from previus versions
                    int i = spec.Versions.Count - 1;
                    if (i >= 0)
                    {
                        var previousVersion = spec.Versions[i];

                        foreach (var g in previousVersion.Groups)
                        {
                            version.Groups.Add(g.Clone());
                        }

                        foreach (var c in previousVersion.Commands)
                        {
                            version.Commands.Add(c.Clone());
                        }
                    }

                    // Include all new enums and commands
                    foreach (var require in feature.Elements("require"))
                    {
                        foreach (var enumElem in require.Elements("enum"))
                        {
                            var enumName = enumElem.Attribute("name").Value;

                            // if enum doesn't exists
                            bool exists = version.Groups.Exists(g => g.Enums.Exists(e => e.Name == enumName));

                            if (!exists)
                            {
                                // Find group
                                string groupFound = FindGroupInXML(file, enumName);

                                // The group already exists
                                GlGroup glgroup = version.Groups.Find(g => g.Name == groupFound);

                                if (glgroup == null)
                                {
                                    glgroup = new GlGroup()
                                    {
                                        Name = groupFound
                                    };
                                    version.Groups.Add(glgroup);
                                }

                                // Create new Enum
                                var glEnum = new GLEnum();
                                glEnum.Initialize(file, enumName);
                                glgroup.Enums.Add(glEnum);
                            }
                        }

                        foreach (var commandElem in require.Elements("command"))
                        {
                            var glCommand = new GLCommand()
                            {
                                Name = commandElem.Attribute("name").Value
                            };
                            if (version.Commands.Find(c => c.Name == glCommand.Name) == null)
                            {
                                // Create new command
                                glCommand.Initialize(commandElem.Document);
                                version.Commands.Add(glCommand);
                            }
                        }
                    }

                    // Add enum from commands
                    foreach (var commandElem in version.Commands)
                    {
                        // Return Type
                        if (commandElem.ReturnType.Type == "GLenum")
                        {
                            var  selectedGroup = commandElem.ReturnType.Group;
                            bool groupExists   = version.Groups.Exists(g => g.Name == selectedGroup);
                            if (!groupExists)
                            {
                                foreach (var group in file.Root.Element("groups").Elements("group"))
                                {
                                    string groupName = group.Attribute("name").Value;
                                    if (groupName == selectedGroup)
                                    {
                                        GlGroup glgroup = new GlGroup()
                                        {
                                            Name = selectedGroup
                                        };
                                        foreach (var e in group.Elements("enum"))
                                        {
                                            GLEnum glEnum   = new GLEnum();
                                            var    enumName = e.Attribute("name").Value;
                                            glEnum.Initialize(file, enumName);
                                            glgroup.Enums.Add(glEnum);
                                        }
                                        version.Groups.Add(glgroup);
                                    }
                                }
                            }
                        }

                        // Parameters
                        foreach (var param in commandElem.Parameters)
                        {
                            if (param.Type == "GLenum")
                            {
                                bool groupExists = version.Groups.Exists(g => g.Name == param.Group);
                                if (!groupExists)
                                {
                                    foreach (var group in file.Root.Element("groups").Elements("group"))
                                    {
                                        string groupName = group.Attribute("name").Value;
                                        if (groupName == param.Group)
                                        {
                                            GlGroup glgroup = new GlGroup()
                                            {
                                                Name = param.Group
                                            };
                                            foreach (var e in group.Elements("enum"))
                                            {
                                                GLEnum glEnum   = new GLEnum();
                                                var    enumName = e.Attribute("name").Value;
                                                glEnum.Initialize(file, enumName);
                                                glgroup.Enums.Add(glEnum);
                                            }
                                            version.Groups.Add(glgroup);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // Remove any anums and commands
                    foreach (var remove in feature.Elements("remove"))
                    {
                        foreach (var e in remove.Elements("enum"))
                        {
                            foreach (var group in version.Groups)
                            {
                                var glenum = group.Enums.Find(n => n.Name == e.Attribute("name").Value);

                                if (glenum != null)
                                {
                                    group.Enums.Remove(glenum);
                                }
                            }
                        }

                        foreach (var c in remove.Elements("command"))
                        {
                            version.Commands.RemoveAll(command => command.Name == c.Attribute("name").Value);
                        }
                    }

                    // Remove all group with 0 enums
                    version.Groups.RemoveAll(g => g.Enums.Count == 0);

                    // Remove GLBoolean type
                    version.Groups.RemoveAll(g => g.Name == "Boolean");

                    spec.Versions.Add(version);
                }
            }

            return(spec);
        }
예제 #2
0
        private static void GenerateBindings(string glFile, DirectoryInfo workingDirectory, string[] api, string namespaceText, string nativeClassText)
        {
            var spec = GLParser.FromFile(glFile, api);

            // Select version
            var version = spec.Versions[spec.Versions.Count - 1];

            // Write Enums
            using (var writer = new StreamWriter((Path.Combine(workingDirectory.FullName, "Enums.cs"))))
            {
                writer.WriteLine("using System;\n");
                writer.WriteLine(namespaceText);
                writer.WriteLine("{");

                int count = 0;
                foreach (var groupElem in version.Groups)
                {
                    // Separate one line betweens enums
                    if (count++ > 0)
                    {
                        writer.WriteLine();
                    }

                    writer.WriteLine($"\tpublic enum {groupElem.Name} : uint");
                    writer.WriteLine("\t{");
                    foreach (var enumElem in groupElem.Enums)
                    {
                        if (IsUint(enumElem.Value))
                        {
                            writer.WriteLine($"\t\t{enumElem.ShortName} = {enumElem.Value},");
                        }
                    }
                    writer.WriteLine("\t}");
                }
                writer.WriteLine("}");
            }

            // Write Commands
            using (var writer = new StreamWriter((Path.Combine(workingDirectory.FullName, $"{nativeClassText}.cs"))))
            {
                writer.WriteLine("using System;");
                writer.WriteLine("using System.Runtime.InteropServices;\n");
                writer.WriteLine(namespaceText);
                writer.WriteLine("{");
                writer.WriteLine($"\tpublic static unsafe class {nativeClassText}");
                writer.WriteLine("\t{");
                writer.WriteLine("\t\tprivate static Func<string, IntPtr> s_getProcAddress;\n");
                writer.WriteLine("\t\tprivate const CallingConvention CallConv = CallingConvention.Winapi;");

                // Prototypes
                foreach (var command in version.Commands)
                {
                    writer.WriteLine("\n\t\t[UnmanagedFunctionPointer(CallConv)]");

                    // Delegate
                    StringBuilder delegateCommand = new StringBuilder("\t\tprivate delegate ");
                    BuildReturnType(version, command, delegateCommand);
                    delegateCommand.Append($" {command.Name}_t(");
                    BuildParameterList(version, command, delegateCommand);
                    delegateCommand.Append(");");
                    writer.WriteLine(delegateCommand.ToString());

                    // internal function
                    writer.WriteLine($"\t\tprivate static {command.Name}_t p_{command.Name};");

                    // public function
                    StringBuilder function = new StringBuilder($"\t\tpublic static ");
                    BuildReturnType(version, command, function);
                    function.Append($" {command.Name}(");
                    BuildParameterList(version, command, function);
                    function.Append($") => p_{command.Name}(");
                    BuildParameterNamesList(command, function);
                    function.Append(");");
                    writer.WriteLine(function.ToString());
                }

                // Helper functions
                writer.WriteLine("\n\t\tpublic static void LoadGetString(Func<string, IntPtr> getProcAddress)");
                writer.WriteLine("\t\t{");
                writer.WriteLine("\t\t\ts_getProcAddress = getProcAddress;");
                writer.WriteLine("\t\t\tLoadFunction(\"glGetString\", out p_glGetString);");
                writer.WriteLine("\t\t}");

                writer.WriteLine("\n\t\tpublic static void LoadAllFunctions(Func<string, IntPtr> getProcAddress)");
                writer.WriteLine("\t\t{");
                writer.WriteLine("\t\t\ts_getProcAddress = getProcAddress;\n");

                foreach (var command in version.Commands)
                {
                    writer.WriteLine($"\t\t\tLoadFunction(\"{command.Name}\", out p_{command.Name});");
                }
                writer.WriteLine("\t\t}\n");

                writer.WriteLine("\t\tprivate static void LoadFunction<T>(string name, out T field)");
                writer.WriteLine("\t\t{");
                writer.WriteLine("\t\t\tIntPtr funcPtr = s_getProcAddress(name);");
                writer.WriteLine("\t\t\tif (funcPtr != IntPtr.Zero)");
                writer.WriteLine("\t\t\t{");
                writer.WriteLine("\t\t\t\tfield = Marshal.GetDelegateForFunctionPointer<T>(funcPtr);");
                writer.WriteLine("\t\t\t}");
                writer.WriteLine("\t\t\telse");
                writer.WriteLine("\t\t\t{");
                writer.WriteLine("\t\t\t\tfield = default(T);");
                writer.WriteLine("\t\t\t}");
                writer.WriteLine("\t\t}");

                writer.WriteLine("\t}");
                writer.WriteLine("}");
            }
        }