void ParseNativeInterface(XElement top, VkCommandInfo result) { var function = new VkNativeInterface(); function.Name = result.Name; function.ReturnType = result.CsReturnType; int index = 0; foreach (var param in top.Elements("param")) { var arg = new VkFunctionArgument { Index = index }; var tokens = param.Value.Split(new[] { ' ', '[', ']' }, StringSplitOptions.RemoveEmptyEntries); arg.IsFixedArray = false; if (tokens.Length == 2) { // usually instance arg.ArgumentCppType = tokens [0]; arg.IsConst = false; // or int } else if (tokens.Length == 3) { // possible const pointer arg.IsConst = (tokens [0] == "const"); arg.ArgumentCppType = tokens [1]; } else if (tokens.Length == 4) { // const float array arg.IsConst = (tokens [0] == "const"); arg.ArgumentCppType = tokens [1]; arg.ArrayConstant = tokens [3]; arg.IsFixedArray = true; } arg.IsPointer = arg.ArgumentCppType.IndexOf('*') >= 0; arg.Name = param.Element("name").Value; arg.BaseCppType = param.Element("type").Value; arg.BaseCsType = GetTypeCsName(arg.BaseCppType); XAttribute optionalAttr = param.Attribute("optional"); arg.IsOptional = optionalAttr != null && optionalAttr.Value == "true"; XAttribute lengthAttr = param.Attribute("len"); if (lengthAttr != null) { var lengths = lengthAttr.Value.Split(',').Where(s => s != "null-terminated").ToArray(); if (lengths.Length != 1) { throw new NotImplementedException(string.Format("param.len != 1 ({0} found)", lengths.Length)); } arg.LengthVariable = lengths [0]; } function.Arguments.Add(arg); // DETERMINE CSHARP TYPE if (arg.ArgumentCppType == "char*") { arg.ArgumentCsType = "string"; } else if (arg.ArgumentCppType == "void*") { arg.ArgumentCsType = "IntPtr"; } else { HandleInfo found; if (Handles.TryGetValue(arg.BaseCsType, out found)) { arg.ArgumentCsType = (found.type == "VK_DEFINE_HANDLE") ? "IntPtr" : "UInt64"; } else { arg.ArgumentCsType = arg.BaseCsType; } } arg.UseOut = !arg.IsConst && arg.IsPointer; ++index; } result.NativeFunction = function; }
void ParseNativeInterface(XElement top, VkCommandInfo result) { var function = new VkNativeInterface(); function.Name = result.Name; function.ReturnType = result.CsReturnType; int index = 0; foreach (var param in top.Elements("param")) { var arg = new VkFunctionArgument { Index = index }; var tokens = param.Value.Split(new[] { ' ', '[', ']' }, StringSplitOptions.RemoveEmptyEntries); arg.IsFixedArray = false; if (tokens.Length == 2) { // usually instance arg.ArgumentCppType = tokens [0]; arg.IsConst = false; // or int } else if (tokens.Length == 3) { // possible const pointer arg.IsConst = (tokens [0] == "const"); arg.ArgumentCppType = tokens [1]; } else if (tokens.Length == 4) { // const float array arg.IsConst = (tokens [0] == "const"); arg.ArgumentCppType = tokens [1]; arg.ArrayConstant = tokens [3]; arg.IsFixedArray = true; } arg.IsPointer = arg.ArgumentCppType.IndexOf('*') >= 0; arg.Name = param.Element("name").Value; arg.BaseCppType = param.Element("type").Value; arg.BaseCsType = mInspector.GetTypeCsName(arg.BaseCppType, "type"); XAttribute optionalAttr = param.Attribute("optional"); arg.IsOptional = optionalAttr != null && optionalAttr.Value == "true"; arg.ByReference = optionalAttr != null && optionalAttr.Value == "false,true"; VkStructInfo structFound; arg.IsStruct = mInspector.Structs.TryGetValue(arg.BaseCsType, out structFound); XAttribute lengthAttr = param.Attribute("len"); if (lengthAttr != null) { var lengths = lengthAttr.Value.Split(',').Where(s => s != "null-terminated").ToArray(); if (lengths.Length != 1) { //throw new NotImplementedException(string.Format("param.len != 1 ({0} found)", lengths.Length)); arg.LengthVariable = null; } else { arg.LengthVariable = lengths[0]; } } function.Arguments.Add(arg); arg.IsNullableIntPtr = arg.IsOptional && arg.IsPointer && !arg.IsFixedArray && arg.LengthVariable == null; // DETERMINE CSHARP TYPE if (arg.ArgumentCppType == "char*") { arg.ArgumentCsType = "string"; } else if (arg.ArgumentCppType == "void*") { arg.ArgumentCsType = "IntPtr"; } else if (arg.ArgumentCppType == "void**") { arg.ArgumentCsType = "IntPtr"; } else { VkHandleInfo found; if (mInspector.Handles.TryGetValue(arg.BaseCsType, out found)) { arg.ArgumentCsType = found.csType; } else if (arg.IsNullableIntPtr) { // REQUIRES MARSHALLING FOR NULLS IN ALLOCATOR arg.ArgumentCsType = "IntPtr"; } else { arg.ArgumentCsType = arg.BaseCsType; } } if (structFound != null && structFound.returnedonly) { arg.UseOut = false; } else { arg.UseOut = !arg.IsConst && arg.IsPointer; } arg.IsBlittable = mInspector.BlittableTypes.Contains(arg.ArgumentCsType); ++index; } // USE POINTER / unsafe ONLY IF // ALL ARGUMENTS ARE BLITTABLE // && >= 1 ARGUMENTS // && >= 1 BLITTABLE STRUCT && NOT OPTIONAL POINTER bool useUnsafe = function.Arguments.Count > 0; uint noOfBlittableStructs = 0; foreach (var arg in function.Arguments) { if (!arg.IsBlittable) { useUnsafe = false; } if (arg.IsStruct && arg.IsBlittable && !arg.IsNullableIntPtr) { noOfBlittableStructs++; } } function.UseUnsafe = useUnsafe && noOfBlittableStructs > 0; // Add [In, Out] attribute to struct array variables if (!function.UseUnsafe) { foreach (var arg in function.Arguments) { if (arg.LengthVariable != null && arg.IsStruct && !arg.IsBlittable) { // SINGULAR MARSHALLED STRUCT ARRAY INSTANCES arg.Attribute = "[In, Out]"; } else if (arg.IsFixedArray && !arg.IsStruct && arg.IsBlittable) { // PRETTY MUCH FOR BLENDCONSTANTS arg.Attribute = string.Format("[MarshalAs(UnmanagedType.LPArray, SizeConst = {0})]", arg.ArrayConstant); } else if (arg.IsStruct && !arg.IsBlittable && !arg.IsNullableIntPtr) { // SINGULAR MARSHALLED STRUCT INSTANCES arg.Attribute = "[In, Out]"; } //else //{ // // Add attribute // VkStructInfo readOnlyStruct; // if (!arg.IsOptional && mInspector.Structs.TryGetValue(arg.BaseCsType, out readOnlyStruct) && readOnlyStruct.returnedonly) // arg.Attribute = "[In, Out]"; //} } } result.NativeFunction = function; }