public DotNetCommandData Clone() { var copy = new DotNetCommandData() { IsFromSpec = this.IsFromSpec, OriginalName = this.OriginalName, NativeName = this.NativeName, DotNetName = this.DotNetName, NativeReturnType = this.NativeReturnType, VersionMajor = this.VersionMajor, VersionMinor = this.VersionMinor, IsUnsafe = this.IsUnsafe, ShouldUseGenerics = this.ShouldUseGenerics, Description = this.Description }; foreach (var param in this.Params) copy.Params.Add(param.Clone()); return copy; }
private void ParseDocs(DotNetCommandData command, Options options) { string docFileName = this.GetDocsFileName(command, options); if (!File.Exists(docFileName)) return; string docText = File.ReadAllText(docFileName); docText = ScrubDocs(docText); var document = XDocument.Parse(docText); var ns = document.Root.GetDefaultNamespace(); command.Description = ScrubDescription(document.Root.Descendants(ns + "refpurpose").First().Value); if (!command.Params.Any()) return; var paramsNode = document.Root.Descendants(ns + "refsect1").First(); if (paramsNode != null) { foreach (var paramNode in paramsNode.Descendants(ns + "varlistentry")) { string paramName = paramNode.Element(ns + "term").Element(ns + "parameter").Value; var param = command.Params.SingleOrDefault(x => x.OriginalName == paramName); if (param != null) { string description = ScrubDescription(paramNode.Element(ns + "listitem").Element(ns + "para").Value); param.Description = description; } } } }
private string GetDocsFileName(DotNetCommandData command, Options options) { string docCommandName = "gl" + command.NativeName; string docFileName = Path.Combine(options.DocsFolder, docCommandName + ".xml"); while (!File.Exists(docFileName) && docCommandName.Length > 0) { docCommandName = docCommandName.Substring(0, docCommandName.Length - 1); docFileName = Path.Combine(options.DocsFolder, docCommandName + ".xml"); } return docFileName; }
private DotNetCommandData ChangeFunctionParamsToEnums(DotNetCommandData function, IEnumerable<XmlCommandParamData> @params) { var copy = function.Clone(); copy.IsFromSpec = false; foreach (var param in @params) { var dotNetParam = copy.Params.Single(x => x.OriginalName == param.Name); dotNetParam.DotNetType = param.TypeGroup; dotNetParam.IsEnum = true; } return copy; }
private DotNetCommandData ChangeFunctionParamsToRefOrOut(DotNetCommandData function, IEnumerable<string> @params) { var copy = function.Clone(); copy.IsFromSpec = false; foreach (var param in copy.Params.Where(x => @params.Contains(x.OriginalName))) { param.DotNetType = param.DotNetType.Replace("[]", ""); if (param.IsOutput) { param.ShouldUseOut = true; } else { param.ShouldUseRef = true; } param.ShouldUseAddressOfOperator = true; } return copy; }
private DotNetCommandData ChangeFunctionParamsToIntPtr(DotNetCommandData function, IEnumerable<string> @params) { var copy = function.Clone(); copy.IsFromSpec = false; foreach (var param in copy.Params.Where(x => @params.Contains(x.OriginalName))) { param.DotNetType = "IntPtr"; param.ShouldUseGenerics = false; param.ShouldUseFixed = false; } if (!copy.Params.Any(x => x.IsPointer)) copy.IsUnsafe = false; if (!copy.Params.Any(x => x.ShouldUseGenerics)) copy.ShouldUseGenerics = false; return copy; }
private void TranslateCommands(XmlSpecData spec, DotNetApiData api, Options options) { foreach (var specCommand in spec.Commands.Where(x => options.CommandFilter(x))) { var specFeature = spec.Features.Where(x => x.AddedCommands.Contains(specCommand.Name)).FirstOrDefault(); var commandData = new DotNetCommandData() { IsFromSpec = true, OriginalName = specCommand.Name, NativeName = this.InflectFunctionNativeName(specCommand.Name, options), DotNetName = this.InflectFunctionDotNetName(specCommand.Name, options), NativeReturnType = this.InflectNativeReturnType(specCommand) }; if (specFeature != null) { commandData.VersionMajor = specFeature.VersionMajor; commandData.VersionMinor = specFeature.VersionMinor; } if (commandData.NativeReturnType == "string") commandData.IsUnsafe = true; foreach (var specCommandParam in specCommand.Params) { var functionParamData = new DotNetCommandParamData() { OriginalName = specCommandParam.Name, Name = this.InflectFunctionParamName(specCommandParam.Name), OriginalType = specCommandParam.Type, NativeType = this.InflectFunctionParamNativeType(specCommandParam), DotNetType = this.InflectFunctionParamDotNetType(specCommandParam), IsPointer = this.IsTypePointer(specCommandParam.Type), IsOutput = this.IsTypeOutput(specCommandParam.Type), ShouldUseGenerics = this.ShouldUseGenericsForType(specCommandParam.Type), ShouldUseFixed = this.ShouldUseFixedForParam(specCommandParam), ShouldUseAddressOfOperator = this.ShouldUseAddressOfOperatorForParam(specCommandParam) }; if (functionParamData.IsPointer) commandData.IsUnsafe = true; if (functionParamData.ShouldUseGenerics) commandData.ShouldUseGenerics = true; if (functionParamData.IsOutput && functionParamData.DotNetType == "IntPtr") { functionParamData.ShouldUseOut = true; } commandData.Params.Add(functionParamData); } api.Commands.Add(commandData); if (options.DocsFolder != null) { this.ParseDocs(commandData, options); } // Create overload which accepts the Enum variant. if (specCommand.Params.Any(x => this.IsTypeEnum(x, api))) { api.Commands.Add(this.ChangeFunctionParamsToEnums(commandData, specCommand.Params.Where(x => this.IsTypeEnum(x, api)))); } } foreach (var commandData in api.Commands.ToArray()) { var specCommand = spec.Commands.Single(x => x.Name == commandData.OriginalName); // Commands which take a pointer and it could be a single element. if (specCommand.Params.Any(x => this.ShouldChangeFunctionParamToRefOrOut(x))) { api.Commands.Add(this.ChangeFunctionParamsToRefOrOut(commandData, specCommand.Params.Where(x => this.ShouldChangeFunctionParamToRefOrOut(x)).Select(x => x.Name))); } // Commands which take a pointer and it could be a single element. if (specCommand.Params.Any(x => this.ShouldChangeFunctionParamToIntPtr(x))) { api.Commands.Add(this.ChangeFunctionParamsToIntPtr(commandData, specCommand.Params.Where(x => this.ShouldChangeFunctionParamToIntPtr(x)).Select(x => x.Name))); } } api.Commands.Sort((x, y) => x.OriginalName != null && y.OriginalName != null ? x.OriginalName.CompareTo(y.OriginalName) : 0); }
private string GetDotNetDeclaration(string padding, DotNetCommandData command, Options options) { string output = string.Empty; output += padding + "/// <summary>" + Environment.NewLine; output += padding + $"/// ({command.OriginalName}) {command.Description}" + Environment.NewLine; output += padding + "/// Since version: " + command.VersionMajor + "." + command.VersionMinor + Environment.NewLine; output += padding + "/// </summary>" + Environment.NewLine; foreach (var param in command.Params) output += padding + $"/// <param name=\"{param.Name.TrimStart('@')}\">{param.Description}</param>" + Environment.NewLine; output += padding + GetSignature("public ", command, true); output += Environment.NewLine + padding + "{" + Environment.NewLine; string bodyPadding = padding + "\t"; if (command.NativeReturnType != "void") output += bodyPadding + command.NativeReturnType + " result;" + Environment.NewLine + Environment.NewLine; if (command.Params.Any(x => x.ShouldUseOut && !x.ShouldUseFixed)) { foreach (var param in command.Params.Where(x => x.ShouldUseOut && !x.ShouldUseFixed)) { output += bodyPadding + param.Name + " = default(" + param.DotNetType + ");" + Environment.NewLine; } output += Environment.NewLine; } bool wrapInTryFinally = command.ShouldUseGenerics; if (command.IsUnsafe) { output += bodyPadding + "unsafe" + Environment.NewLine; output += bodyPadding + "{" + Environment.NewLine; bodyPadding += "\t"; if (command.IsAtLeastOneParamNonVoidPointer) { foreach (var param in command.Params) { if (param.ShouldUseFixed) { output += bodyPadding + "fixed (" + param.NativeType + " " + param.Name + "Ptr = "; if (param.ShouldUseAddressOfOperator) output += "&"; output += param.Name + ")" + Environment.NewLine; } } output += bodyPadding + "{" + Environment.NewLine; bodyPadding += "\t"; } } if (wrapInTryFinally) { foreach (var param in command.Params) { if (param.ShouldUseGenerics) output += bodyPadding + "GCHandle " + param.Name + "Ptr = GCHandle.Alloc(" + param.Name + ", GCHandleType.Pinned);" + Environment.NewLine; } output += bodyPadding + "try" + Environment.NewLine; output += bodyPadding + "{" + Environment.NewLine; bodyPadding += "\t"; } output += bodyPadding; if (command.NativeReturnType != "void") output += "result = "; if (command.NativeReturnType == "string") output += "new string ((sbyte*)"; output += "this._" + command.NativeName + "(" + this.GetMethodCallParamsList(command); if (command.NativeReturnType == "string") output += ")"; output += ");" + Environment.NewLine; if (wrapInTryFinally) { bodyPadding = bodyPadding.Substring(0, bodyPadding.Length - 1); output += bodyPadding + "}" + Environment.NewLine; output += bodyPadding + "finally" + Environment.NewLine; output += bodyPadding + "{" + Environment.NewLine; if (command.ShouldUseGenerics) { foreach (var param in command.Params) { if (param.ShouldUseGenerics) output += bodyPadding + "\t" + param.Name + "Ptr.Free();" + Environment.NewLine; } } output += bodyPadding + "}" + Environment.NewLine; } if (command.IsUnsafe) { if (command.IsAtLeastOneParamNonVoidPointer) { bodyPadding = bodyPadding.Substring(0, bodyPadding.Length - 1); output += bodyPadding + "}" + Environment.NewLine; } bodyPadding = bodyPadding.Substring(0, bodyPadding.Length - 1); output += bodyPadding + "}" + Environment.NewLine; } if (command.NativeReturnType != "void") output += Environment.NewLine + bodyPadding + "return result;" + Environment.NewLine; output += padding + "}"; return output; }
private string GetMethodCallParamsList(DotNetCommandData function) { string output = string.Empty; if (function.Params.Count > 0) { for (int i = 0; i < function.Params.Count; i++) { var param = function.Params[i]; if (param.ShouldUseGenerics) { output += "(IntPtr)"; } else if (param.IsEnum) { output += "(uint)"; } output += param.Name; if (param.ShouldUseFixed || param.ShouldUseGenerics) { output += "Ptr"; } if (param.ShouldUseGenerics) { output += ".AddrOfPinnedObject()"; } if (i != function.Params.Count - 1) output += ", "; } } return output; }
private string GetDelegateDeclaration(string padding, DotNetCommandData function) { string prefix = "public delegate "; if (function.IsUnsafe) prefix = "public unsafe delegate "; string signature = this.GetSignature(padding + prefix, function, false) + ";"; return signature; }
private string GetPInvokeDeclaration(string padding, DotNetCommandData command, bool asPublic) { string header = padding + "[System.Runtime.InteropServices.DllImport(Library, EntryPoint=\"" + command.OriginalName + "\", ExactSpelling=true)]" + Environment.NewLine; string prefix = string.Empty; if (asPublic) prefix = "public "; else prefix = "internal "; prefix += "static extern "; if (command.IsUnsafe) prefix += "unsafe "; string signature = this.GetSignature(padding + prefix, command, false) + ";"; return header + signature; }
private string GetSignature(string prefix, DotNetCommandData function, bool useDotNetStyle) { string signature = prefix; string returnType = function.NativeReturnType; if (returnType == "GLenum" || returnType == "GLbitfield") returnType = "uint"; string functionName = (useDotNetStyle ? function.DotNetName : function.NativeName); signature += returnType + " " + functionName; if (useDotNetStyle && function.ShouldUseGenerics) signature += "<T>"; signature += "("; int i = 0; foreach (var param in function.Params) { if (!useDotNetStyle) { if (param.IsOutput) signature += "[Out] "; } else { if (param.ShouldUseRef) { signature += "ref "; } else if (param.ShouldUseOut) { signature += "out "; } } signature += (useDotNetStyle ? param.DotNetType : param.NativeType) + " " + param.Name; if (i < function.Params.Count - 1) signature += ", "; i++; } signature += ")"; if (useDotNetStyle && function.ShouldUseGenerics) signature += " where T : struct"; return signature; }