public static bool TryParse(XmlElement command, List <string> errors, out CommandBinding binding) { XmlElement proto = (XmlElement)command.GetElementsByTagName("proto").Item(0); binding = new CommandBinding { ReturnCType = (proto.GetElementsByTagName("ptype").OfType <XmlElement>().FirstOrDefault()?.InnerText ?? proto.ChildNodes.OfType <XmlText>().First().Value).Trim() }; if (TypeConverter.Convert(command.OwnerDocument, binding.ReturnCType, out binding.ReturnCSType) && binding.ReturnCSType.ReturnType != null) { binding.CName = proto.GetElementsByTagName("name").Item(0).InnerText.Trim(); binding.CSName = binding.CName.CommandToPascal(); foreach (XmlElement param in command.GetElementsByTagName("param")) { ParameterBinding parameterBinding; if (ParameterBinding.TryParse(param, errors, out parameterBinding)) { binding.Parameters.Add(parameterBinding); } else { return(false); } } return(true); } else { errors.Add(string.Format("Unable to find method to convert type '{0}.'", binding.ReturnCType)); return(false); } }
void ImplementMethod(StringBuilder code, List <string> errors, CommandBinding binding, int i, string indent) { if (i < binding.Parameters.Count) { ParameterBinding param = binding.Parameters[i]; if (param.CSType.ParameterType.EndsWith("[][][]")) { errors.Add("Type has too many array dimensions."); code.Append(indent); code.AppendLine("throw new NotSupportedException();"); } else if (param.CSType.ParameterType.EndsWith("[][]")) { ImplementDoubleArrayMethod(code, errors, binding, i, indent, param.Name, param.CSType.ParameterType.Substring(0, param.CSType.ParameterType.Length - 4), param); } else if (param.CSType.ParameterType.EndsWith("[]")) { code.AppendFormat("{0}fixed ({1} *ptr_{2} = @{2}) {3}", indent, param.CSType.ParameterType.Substring(0, param.CSType.ParameterType.Length - 2), param.Name, '{'); code.AppendLine(); param.Name = string.Concat("ptr_", param.Name); ImplementMethod(code, errors, binding, i + 1, string.Concat(indent, " ")); code.Append(indent); code.AppendLine("}"); } else { ImplementMethod(code, errors, binding, i + 1, indent); } } else { code.Append(indent); if (binding.ReturnCSType.ReturnType != "void") { code.Append("return "); } code.AppendFormat("Native_{0}(", binding.CSName); bool first = true; foreach (ParameterBinding param in binding.Parameters) { if (first) { first = false; } else { code.Append(", "); } if (param.Name[0] >= 'a' && param.Name[0] <= 'z') { code.Append("@"); } code.AppendFormat(param.Name); } code.AppendLine(");"); } }
public static bool TryParse(XmlElement param, List <string> errors, out ParameterBinding binding) { ParameterBinding _binding = binding = new ParameterBinding(); if (param.HasAttribute("group")) { XmlElement groups = (XmlElement)param.OwnerDocument.GetElementsByTagName("groups").Item(0); binding.CType = param.Attributes["group"].Value; if (groups.ChildNodes.OfType <XmlElement>().Any(e => e.Attributes["name"].Value == _binding.CType)) { string csType = string.Concat("Gl", binding.CType); csType = string.Concat(csType, new string(param.ChildNodes.OfType <XmlText>().SelectMany(n => n.Value).Where(v => v == '*').SelectMany(c => "[]").ToArray())); binding.CSType = new ConvertedType(csType); } } if (binding.CSType == null) { XmlElement ptype = (XmlElement)param.GetElementsByTagName("ptype").Item(0); if (ptype == null) { binding.CType = param.ChildNodes.OfType <XmlText>().First().Value.Trim(); } else { binding.CType = ptype.InnerText.Trim(); binding.CType = string.Concat(binding.CType, new string(param.ChildNodes.OfType <XmlText>().SelectMany(n => n.Value).Where(v => v == '*').ToArray())); } ConvertedType t; if (TypeConverter.Convert(param.OwnerDocument, binding.CType, out t) && t.ParameterType != null) { binding.CSType = t; } else { errors.Add(string.Format("Unable to find method to convert type '{0}.'", binding.CType)); return(false); } } XmlElement paramName = (XmlElement)param.GetElementsByTagName("name").Item(0); binding.Name = paramName.InnerText.Trim(); return(true); }
void ImplementDoubleArrayMethod(StringBuilder code, List <string> errors, CommandBinding binding, int i, string indent, string paramName, string arrayType, ParameterBinding param) { code.AppendFormat("{0}IntPtr ptr_{1} = Marshal.AllocHGlobal(@{1}.Length * sizeof(void *));", indent, paramName); code.AppendLine(); code.AppendFormat("{0}try {1}", indent, '{'); code.AppendLine(); code.AppendFormat("{0} {4}ConvertDoubleArray_{1}(ptr_{2}, @{2}, (void **) ptr_{2}.ToPointer(), 0, __fixedLocals => {3}", indent, arrayType, paramName, '{', binding.ReturnCSType.ReturnType == "void" ? "" : "return "); code.AppendLine(); param.Name = string.Format("({0} **) ptr_{1}.ToPointer()", arrayType, paramName); List <string> fixedLocals = new List <string>(); for (int j = 0, k = 0; j < i; ++j) { if (binding.Parameters[j].CSType.ParameterType.EndsWith("[]")) { fixedLocals.Add(binding.Parameters[j].Name); binding.Parameters[j].Name = string.Format("({0} *) __fixedLocals[{1}]", binding.Parameters[j].CSType.ParameterType.Substring(0, binding.Parameters[j].CSType.ParameterType.Length - 2), k++); } } ImplementMethod(code, errors, binding, i + 1, string.Concat(indent, " ")); code.AppendFormat("{0} {1}", indent, '}'); if (fixedLocals.Count == 0) { code.Append(", new void *[0]"); } else { foreach (string fixedLocal in fixedLocals) { code.AppendFormat(", {0}", fixedLocal); } } code.AppendLine(");"); code.AppendFormat("{0}{1} finally {2}", indent, '}', '{'); code.AppendLine(); code.AppendFormat("{0} Marshal.FreeHGlobal(ptr_{1});", indent, paramName); code.AppendLine(); code.AppendFormat("{0}{1}", indent, '}'); code.AppendLine(); }