private void WriteFunctions()

in utils/SkiaSharpGenerator/Generate/Generator.cs [438:527]


		private void WriteFunctions(TextWriter writer)
		{
			Log?.LogVerbose("  Writing p/invokes...");

			var functionGroups = compilation.Functions
				.Where(f => IncludeNamespace(f.Name))
				.OrderBy(f => f.Name)
				.GroupBy(f => f.Span.Start.File.ToLower().Replace("\\", "/"))
				.OrderBy(g => Path.GetDirectoryName(g.Key) + "/" + Path.GetFileName(g.Key));

			foreach (var group in functionGroups)
			{
				var fullPath = Path.GetFullPath(group.Key).ToLower();
				if (excludedFiles.Any(e => Path.GetFullPath(e).ToLower() == fullPath))
				{
					Log?.LogVerbose($"    Skipping file '{group.Key}' because it was in the exclude list.");
					continue;
				}

				writer.WriteLine($"\t\t#region {Path.GetFileName(group.Key)}");
				foreach (var function in group)
				{
					Log?.LogVerbose($"    {function.Name}");

					var name = function.Name;
					functionMappings.TryGetValue(name, out var funcMap);
					var skipFunction = false;

					var paramsList = new List<string>();
					var paramNamesList = new List<string>();
					for (var i = 0; i < function.Parameters.Count; i++)
					{
						var p = function.Parameters[i];
						var n = string.IsNullOrEmpty(p.Name) ? $"param{i}" : p.Name;
						n = SafeName(n);
						var t = GetType(p.Type);
						var cppT = GetCppType(p.Type);
						if (excludedTypes.Contains(cppT) == true)
						{
							Log?.LogVerbose($"    Skipping function '{function.Name}' because parameter '{cppT}' was in the exclude list.");
							skipFunction = true;
							break;
						}
						if (t == "Boolean" || cppT == "bool")
							t = $"[MarshalAs (UnmanagedType.I1)] bool";
						if (funcMap != null && funcMap.Parameters.TryGetValue(i.ToString(), out var newT))
							t = newT;
						paramsList.Add($"{t} {n}");
						paramNamesList.Add(n);
					}

					if (skipFunction)
						continue;

					var returnType = GetType(function.ReturnType);
					var retAttr = "";
					if (funcMap != null && funcMap.Parameters.TryGetValue("-1", out var newR))
					{
						returnType = newR;
					}
					else if (returnType == "Boolean" || GetCppType(function.ReturnType) == "bool")
					{
						returnType = "bool";
						retAttr = $"[return: MarshalAs (UnmanagedType.I1)]";
					}

					writer.WriteLine();
					writer.WriteLine($"\t\t// {function}");
					writer.WriteLine($"\t\t#if !USE_DELEGATES");
					writer.WriteLine($"\t\t[DllImport ({config.DllName}, CallingConvention = CallingConvention.Cdecl)]");
					if (!string.IsNullOrEmpty(retAttr))
						writer.WriteLine($"\t\t{retAttr}");
					writer.WriteLine($"\t\tinternal static extern {returnType} {name} ({string.Join(", ", paramsList)});");
					writer.WriteLine($"\t\t#else");
					writer.WriteLine($"\t\tprivate partial class Delegates {{");
					writer.WriteLine($"\t\t\t[UnmanagedFunctionPointer (CallingConvention.Cdecl)]");
					if (!string.IsNullOrEmpty(retAttr))
						writer.WriteLine($"\t\t\t{retAttr}");
					writer.WriteLine($"\t\t\tinternal delegate {returnType} {name} ({string.Join(", ", paramsList)});");
					writer.WriteLine($"\t\t}}");
					writer.WriteLine($"\t\tprivate static Delegates.{name} {name}_delegate;");
					writer.WriteLine($"\t\tinternal static {returnType} {name} ({string.Join(", ", paramsList)}) =>");
					writer.WriteLine($"\t\t\t({name}_delegate ??= GetSymbol<Delegates.{name}> (\"{name}\")).Invoke ({string.Join(", ", paramNamesList)});");
					writer.WriteLine($"\t\t#endif");
				}
				writer.WriteLine();
				writer.WriteLine($"\t\t#endregion");
				writer.WriteLine();
			}
		}