private DotNetFunctionData ChangeFunctionParamsToRefOrOut(DotNetFunctionData function, IEnumerable<string> @params) { var copy = function.Clone(); copy.IsNative = false; //if (function.OriginalName == "glShaderBinary") // Console.WriteLine("Stop"); 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 DotNetFunctionData ChangeFunctionParamsToEnums(DotNetFunctionData function, IEnumerable<XmlCommandParamData> @params) { var copy = function.Clone(); copy.IsNative = 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 DotNetFunctionData ChangeFunctionParamsToIntPtr(DotNetFunctionData function, IEnumerable<string> @params) { var copy = function.Clone(); copy.IsNative = 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 TranslateFunctions(XmlSpecData spec, DotNetApiData api, Options options) { foreach (var specCommand in spec.Commands.Where(x => options.CommandFilter(x))) { var specFeature = spec.Features.Where(x => x.Commands.Contains(specCommand.Name)).FirstOrDefault(); var functionData = new DotNetFunctionData() { IsNative = true, OriginalName = specCommand.Name, NativeName = this.InflectFunctionNativeName(specCommand.Name, options), DotNetName = this.InflectFunctionDotNetName(specCommand.Name, options), OriginalReturnType = specCommand.ReturnType, NativeReturnType = this.InflectNativeReturnType(specCommand), DotNetReturnType = this.InflectDotNetReturnType(specCommand) }; if (specFeature != null) { functionData.VersionMajor = specFeature.VersionMajor; functionData.VersionMinor = specFeature.VersionMinor; functionData.CanPInvoke = specFeature.VersionMajor == 1 && specFeature.VersionMinor <= 1; } if (functionData.NativeReturnType == "string") functionData.IsUnsafe = true; foreach (var specCommandParam in specCommand.Params) { var functionParamData = new DotNetFunctionParamData() { 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) functionData.IsUnsafe = true; if (functionParamData.ShouldUseGenerics) functionData.ShouldUseGenerics = true; if (functionParamData.IsOutput && functionParamData.DotNetType == "IntPtr") { functionParamData.ShouldUseOut = true; } functionData.Params.Add(functionParamData); } api.Functions.Add(functionData); // Create overload which accepts the Enum variant. if (specCommand.Params.Any(x => this.IsTypeEnum(x, api))) { api.Functions.Add(this.ChangeFunctionParamsToEnums(functionData, specCommand.Params.Where(x => this.IsTypeEnum(x, api)))); } } foreach (var functionData in api.Functions.ToArray()) { var specCommand = spec.Commands.Single(x => x.Name == functionData.OriginalName); // Commands which take a pointer and it could be a single element. if (specCommand.Params.Any(x => this.ShouldChangeFunctionParamToRefOrOut(x))) { api.Functions.Add(this.ChangeFunctionParamsToRefOrOut(functionData, 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.Functions.Add(this.ChangeFunctionParamsToIntPtr(functionData, specCommand.Params.Where(x => this.ShouldChangeFunctionParamToIntPtr(x)).Select(x => x.Name))); } } api.Functions.Sort((x, y) => x.OriginalName != null && y.OriginalName != null ? x.OriginalName.CompareTo(y.OriginalName) : 0); }
private string GetSignature(string prefix, DotNetFunctionData 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; }
private string GetNativeDeclaration(string padding, DotNetFunctionData function, bool asPublic) { string header = padding + "[System.Runtime.InteropServices.DllImport(Library, EntryPoint=\"" + function.OriginalName + "\", ExactSpelling=true)]" + Environment.NewLine; string prefix = string.Empty; if (asPublic) prefix = "public "; else prefix = "internal "; prefix += "static extern "; if (function.IsUnsafe) prefix += "unsafe "; string signature = this.GetSignature(padding + prefix, function, false) + ";"; return header + signature; }
private string GetMethodCallParamsList(DotNetFunctionData 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 GetDotNetDeclaration(string padding, DotNetFunctionData function, Options options) { string output = padding + "/// " + function.OriginalName + Environment.NewLine; output += padding + "/// Version: " + function.VersionMajor + "." + function.VersionMinor + Environment.NewLine; output += padding + GetSignature("public ", function, true); output += Environment.NewLine + padding + "{" + Environment.NewLine; string bodyPadding = padding + "\t"; if (function.NativeReturnType != "void") output += bodyPadding + function.NativeReturnType + " result;" + Environment.NewLine + Environment.NewLine; if (function.Params.Any(x => x.ShouldUseOut && !x.ShouldUseFixed)) { foreach (var param in function.Params.Where(x => x.ShouldUseOut && !x.ShouldUseFixed)) { output += bodyPadding + param.Name + " = default(" + param.DotNetType + ");" + Environment.NewLine; } output += Environment.NewLine; } bool wrapInTryFinally = function.ShouldUseGenerics; if (function.IsUnsafe) { output += bodyPadding + "unsafe" + Environment.NewLine; output += bodyPadding + "{" + Environment.NewLine; bodyPadding += "\t"; if (function.IsAtLeastOneParamNonVoidPointer) { foreach (var param in function.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 function.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 (function.NativeReturnType != "void") output += "result = "; if (function.NativeReturnType == "string") output += "new string ((sbyte*)"; if (function.CanPInvoke) output += options.FunctionsClassName + "." + function.NativeName + "(" + this.GetMethodCallParamsList(function); else output += "this._" + function.NativeName + "(" + this.GetMethodCallParamsList(function); if (function.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 (function.ShouldUseGenerics) { foreach (var param in function.Params) { if (param.ShouldUseGenerics) output += bodyPadding + "\t" + param.Name + "Ptr.Free();" + Environment.NewLine; } } output += bodyPadding + "}" + Environment.NewLine; } if (function.IsUnsafe) { if (function.IsAtLeastOneParamNonVoidPointer) { bodyPadding = bodyPadding.Substring(0, bodyPadding.Length - 1); output += bodyPadding + "}" + Environment.NewLine; } bodyPadding = bodyPadding.Substring(0, bodyPadding.Length - 1); output += bodyPadding + "}" + Environment.NewLine; } if (function.NativeReturnType != "void") output += Environment.NewLine + bodyPadding + "return result;" + Environment.NewLine; output += padding + "}"; return output; }
private string GetDelegateDeclaration(string padding, DotNetFunctionData function) { string prefix = "internal delegate "; if (function.IsUnsafe) prefix = "internal unsafe delegate "; string signature = this.GetSignature(padding + prefix, function, false) + ";"; return signature; }
public DotNetFunctionData Clone() { var copy = new DotNetFunctionData() { IsNative = this.IsNative, OriginalName = this.OriginalName, NativeName = this.NativeName, DotNetName = this.DotNetName, OriginalReturnType = this.OriginalReturnType, NativeReturnType = this.NativeReturnType, DotNetReturnType = this.DotNetReturnType, VersionMajor = this.VersionMajor, VersionMinor = this.VersionMinor, CanPInvoke = this.CanPInvoke, IsUnsafe = this.IsUnsafe, ShouldUseGenerics = this.ShouldUseGenerics }; foreach (var param in this.Params) copy.Params.Add(param.Clone()); return copy; }