예제 #1
0
        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;
        }
예제 #2
0
        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;
        }