Exemplo n.º 1
0
        public void Enter(CppFunction cpp_fn)
        {
            var scope = new Scope(cpp_fn);

            scopes.Add(scope);
            functions.Add(cpp_fn);
        }
Exemplo n.º 2
0
        public CsFunction Prepare(CppFunction cppFunction)
        {
            var cSharpFunction = new CsFunction(cppFunction);
            // All functions must have a tag
            var tag = cppFunction.GetMappingRule();

            if (tag == null || tag.Group == null)
            {
                Logger.Error(LoggingCodes.FunctionNotAttachedToGroup, "CppFunction [{0}] is not tagged and attached to any Class/FunctionGroup", cppFunction);
                return(null);
            }

            var csClass = groupRegistry.FindGroup(tag.Group);

            if (csClass == null)
            {
                Logger.Error(LoggingCodes.FunctionNotAttachedToGroup, "CppFunction [{0}] is not attached to a Class/FunctionGroup", cppFunction);
                return(null);
            }

            // Set the DllName for this function
            cSharpFunction.DllName = tag.FunctionDllName;

            // Add the function to the ClassType
            csClass.Add(cSharpFunction);

            return(cSharpFunction);
        }
Exemplo n.º 3
0
    public CsFunction(Ioc ioc, CppFunction cppFunction, string name) : base(ioc, cppFunction, name)
    {
        var tag = cppFunction.Rule;

        // Set the DllName for this function
        DllName = tag.FunctionDllName;
    }
        public static CSharpElement ConvertFunction(CSharpConverter converter, CppFunction cppFunction, CSharpElement context)
        {
            // We process only public export functions
            if (!cppFunction.IsPublicExport() || ((cppFunction.Flags & (CppFunctionFlags.Inline | CppFunctionFlags.Method | CppFunctionFlags.Constructor | CppFunctionFlags.Destructor)) != 0 && (cppFunction.Flags & CppFunctionFlags.Virtual) == 0))
            {
                return(null);
            }

            // Register the struct as soon as possible
            var csFunction = new CSharpMethod()
            {
                CppElement = cppFunction
            };

            var container = converter.GetCSharpContainer(cppFunction, context);

            converter.ApplyDefaultVisibility(csFunction, container);
            container.Members.Add(csFunction);

            converter.AddUsing(container, "System.Runtime.InteropServices");

            if ((cppFunction.Flags & CppFunctionFlags.Virtual) == 0)
            {
                csFunction.Modifiers |= CSharpModifiers.Static | CSharpModifiers.Extern;
            }
            else
            {
                csFunction.Visibility = CSharpVisibility.None;
            }
            csFunction.Name       = converter.GetCSharpName(cppFunction, csFunction);
            csFunction.Comment    = converter.GetCSharpComment(cppFunction, csFunction);
            csFunction.ReturnType = converter.GetCSharpType(cppFunction.ReturnType, csFunction);

            return(csFunction);
        }
Exemplo n.º 5
0
        private CppFunction GetCppFunction(CXType functionType, CXCursor cursor, string functionName)
        {
            var function   = new CppFunction();
            var returnType = clang.getResultType(functionType);

            function.Name    = functionName;
            function.Comment = clang.Cursor_getBriefCommentText(cursor).ToString();
            var returnParam = GetFunctionParamMarshalType(returnType);

            function.ReturnType = returnParam.Type;

            uint i = 0;

            clang.visitChildren(cursor, (cursorParam, cxCursor1, ptr) =>
            {
                if (cursorParam.kind == CXCursorKind.CXCursor_ParmDecl)
                {
                    var argName = clang.getCursorSpelling(cursorParam).ToString();

                    if (string.IsNullOrEmpty(argName))
                    {
                        argName = "param" + i;
                    }

                    var parameter  = GetFunctionParamMarshalType(clang.getArgType(functionType, i));
                    parameter.Name = argName;
                    parameter.Type = parameter.Type.Replace("const ", string.Empty);

                    function.Parameters.Add(parameter);
                    i++;
                }
                return(CXChildVisitResult.CXChildVisit_Continue);
            }, new CXClientData(IntPtr.Zero));
            return(function);
        }
Exemplo n.º 6
0
        /// <summary>
        /// E.g.: "void Foo(int age, char* name)" ==> "ic" (first letters of parameters' types)
        /// </summary>
        public static string ParametersMask(this CppFunction function)
        {
            var sb         = new StringBuilder();
            var parameters = function.Parameters.ToList();

            if (parameters.Count < 1)
            {
                sb.Append("0");
            }
            else
            {
                foreach (var p in parameters)
                {
                    var type = p.Type.GetDisplayName()
                               .Replace("const ", "")
                               .Replace("*", "")
                               .Replace("&", "")
                               .Trim();

                    sb.Append(type[0]);
                }
            }

            return(sb.ToString());
        }
Exemplo n.º 7
0
        public void RegisterCandidates(TypeMapper mapper, List <CppFunction> functions)
        {
            string[] prefixes = { "Is", "Has", "Get" };
            foreach (var f in functions)
            {
                var    pi     = new PropertyInfo(mapper);
                string name   = mapper.RenameForApi(f.Name, true);
                string prefix = prefixes.FirstOrDefault(p => name.StartsWith(p));
                if (prefix != null)
                {
                    if (f.Parameters.Count == 0 && !f.IsConstructor)
                    {
                        pi.GetterFunction = f;
                        pi.GettetApiName  = name;
                        pi.PropertyName   = name.Remove(0, prefix.Length);

                        // looking for setter:
                        CppFunction setter = functions.FirstOrDefault(sf => sf.Parameters.Count == 1 && mapper.RenameForApi(sf.Name, true).StartsWith("Set"));
                        if (setter != null && f.IsStatic() == setter.IsStatic() && !setter.IsConstructor)
                        {
                            pi.SetterFunction = setter;
                            pi.SetterApiName  = mapper.RenameForApi(setter.Name, true);
                        }
                    }
                }

                _candidates.Add(pi);
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Deals with turning the CppFunction types into V types, function name to snake case, params
        /// to snake case and any other data transformations we will need for the V functions
        /// </summary>
        static ParsedFunction ParsedFunctionFromCppFunction(CppFunction cFunc, Config config)
        {
            var f = new ParsedFunction
            {
                Name  = cFunc.Name,
                VName = V.ToSnakeCase(config.StripFunctionPrefix(cFunc.Name))
            };

            // hack to fix ghetto forced 'init' module function
            if (f.VName == "init")
            {
                f.VName = config.ModuleName + "_" + f.VName;
            }

            if (cFunc.ReturnType.GetDisplayName() != "void")
            {
                f.RetType  = cFunc.ReturnType.GetDisplayName();
                f.VRetType = V.GetVType(cFunc.ReturnType);
            }

            foreach (var param in cFunc.Parameters)
            {
                var p = new ParsedParameter
                {
                    Name  = param.Name.EscapeReserved(),
                    VName = V.ToSnakeCase(config.StripFunctionPrefix(param.Name)).EscapeReserved(),
                    Type  = param.Type.GetDisplayName(),
                    VType = V.GetVType(param.Type)
                };
                f.Parameters.Add(p);
            }

            return(f);
        }
Exemplo n.º 9
0
        public static object GetParametersSignature(CppFunction command, bool useTypes = true)
        {
            StringBuilder signature = new StringBuilder();

            foreach (var parameter in command.Parameters)
            {
                string convertedType = ConvertToCSharpType(parameter.Type);
                // Hack for structs that are not bittable
                // https://stackoverflow.com/questions/32110152/c-sharp-marshalling-bool
                if (convertedType == "WGPURenderPipelineDescriptor*" || convertedType == "WGPUBufferDescriptor*")
                {
                    signature.Append("ref ");
                    convertedType = convertedType.Remove(convertedType.Length - 1);
                }
                string convertedName = parameter.Name;

                if (useTypes)
                {
                    signature.Append($"{convertedType} ");
                }

                signature.Append($"{convertedName}, ");
            }

            signature.Length -= 2;

            return(signature.ToString());
        }
Exemplo n.º 10
0
 internal bool IsMethodMarkedAsUnsupported(CppFunction function)
 {
     if (function.Parent is CppClass cppClass)
     {
         return(_unsupportedMethods.Contains(cppClass.GetDisplayName() + "." + function.Name));
     }
     return(_unsupportedMethods.Contains(function.Name));
 }
Exemplo n.º 11
0
        public static bool IsCopyConstructor(this CppFunction function)
        {
            if (!function.IsConstructor || function.Parameters.Count != 1)
            {
                return(false);
            }

            var p = function.Parameters[0].Type.GetDisplayName();

            return(p.StartsWith("const ") && p.Contains("&")); // TODO:
        }
Exemplo n.º 12
0
        public static ExpressionStatementSyntax EmitCalli(TypeInfo returnTypeInfo, CppFunction cppFunction,
                                                          TypeMap typeMap, IReadOnlyDictionary <string, string> delegates)
        {
            return(ExpressionStatement(
                       InvocationExpression(
                           MemberAccessExpression(
                               SyntaxKind.SimpleMemberAccessExpression,
                               MemberAccessExpression(
                                   SyntaxKind.SimpleMemberAccessExpression,
                                   IdentifierName("IL"),
                                   IdentifierName("Emit")),
                               IdentifierName("Calli")),
                           ArgumentList(SingletonSeparatedList(Argument(
                                                                   ObjectCreationExpression(
                                                                       IdentifierName("StandAloneMethodSig"),
                                                                       ArgumentList(SeparatedList(GetMethodSigParameters())),
                                                                       null)))))));

            IEnumerable <ArgumentSyntax> GetMethodSigParameters()
            {
                yield return(Argument(
                                 MemberAccessExpression(
                                     SyntaxKind.SimpleMemberAccessExpression,
                                     IdentifierName(nameof(CallingConvention)),
                                     IdentifierName(nameof(CallingConvention.Cdecl)))));

                if (returnTypeInfo.IsFunction)
                {
                    yield return(Argument(TypeOfExpression(IntPtrName)));
                }
                else
                {
                    yield return(Argument(TypeOfExpression(returnTypeInfo.TypeSyntax)));
                }

                foreach (var cppParameter in cppFunction.Parameters)
                {
                    if (delegates.TryGetValue(cppParameter.Name, out _))
                    {
                        yield return(Argument(TypeOfExpression(IdentifierName(nameof(IntPtr)))));
                    }
                    else if (typeMap.TryResolveType(cppParameter.Type, out var paramTypeInfo))
                    {
                        yield return(Argument(TypeOfExpression(paramTypeInfo.TypeSyntax)));
                    }
                    else
                    {
                        throw new ArgumentException();
                    }
                }
            }
        }
Exemplo n.º 13
0
        private void WriteFunction(CppFunction function)
        {
            var signature = new StringBuilder();

            if (!string.IsNullOrWhiteSpace(function.Comment))
            {
                WriteComment(function.Comment);
            }

            var isPrivate = PrivateFunctions.Contains(function.Name);

            signature.Append((isPrivate ? "private " : "public ") + "static extern ");

            // Function return type
            signature.Append(function.ReturnType);

            signature.Append(" ");

            var functionName = function.Name + (isPrivate ? "Internal" : string.Empty);

            // Function name
            signature.Append(functionName);

            signature.Append("(");
            for (var j = 0; j < function.Parameters.Count; j++)
            {
                var parameter = function.Parameters[j];
                if (j > 0)
                {
                    signature.Append(", ");
                }
                if (parameter.Attributes != null)
                {
                    signature.Append(parameter.Attributes).Append(" ");
                }
                //if (!marshal && j == 0 && handles.Contains(parameter.Type))
                //    signature.Append("this ");
                if (parameter.Qualifier != null)
                {
                    signature.Append(parameter.Qualifier).Append(" ");
                }
                signature.Append(parameter.Type);
                signature.Append(" ");
                signature.Append(parameter.Name);
            }
            signature.Append(")");

            WriteLine(
                $"[DllImport(LibSassDll, EntryPoint = \"{function.Name}\",CallingConvention = CallingConvention.Cdecl)]");
            WriteLine(signature + ";");
        }
Exemplo n.º 14
0
            public Scope(CppFunction cpp_func)
            {
                cpp_item = cpp_func;
                type     = Type.Function;
                get_name = () =>
                {
                    return(cpp_func.Name);
                };

                get_unique_name = () =>
                {
                    // cpp_func.TemplateParameters
                    return("");
                };
            }
Exemplo n.º 15
0
        /// <summary>
        /// Gets a boolean indicating whether the function is a dllexport or visibility("default")
        /// </summary>
        /// <param name="function">The function to check against</param>
        /// <returns><c>true</c> if the function is a dllexport or visibility("default")</returns>
        public static bool IsPublicExport(this CppFunction function)
        {
            if (function.Attributes != null)
            {
                foreach (var attr in function.Attributes)
                {
                    if (attr.IsPublicExport())
                    {
                        return(true);
                    }
                }
            }

            return(function.LinkageKind == CppLinkageKind.External || function.LinkageKind == CppLinkageKind.UniqueExternal);
        }
Exemplo n.º 16
0
        public static object GetParametersSignature(CppFunction command, bool useTypes = true)
        {
            StringBuilder signature = new StringBuilder();

            foreach (var parameter in command.Parameters)
            {
                string convertedType = ConvertToCSharpType(parameter.Type);
                string convertedName = parameter.Name;

                if (useTypes)
                {
                    signature.Append($"{convertedType} ");
                }

                signature.Append($"{convertedName}, ");
            }

            signature.Length -= 2;

            return(signature.ToString());
        }
        private static void EmitInvoke(
            CodeWriter writer,
            CppFunction function,
            List <string> parameters,
            bool handleCheckResult = true)
        {
            var postCall = string.Empty;

            if (handleCheckResult)
            {
                var hasResultReturn = GetCsTypeName(function.ReturnType) == "VkResult";
                if (hasResultReturn)
                {
                    postCall = ".CheckResult()";
                }
            }

            var index = 0;
            var callArgumentStringBuilder = new StringBuilder();

            foreach (var parameterName in parameters)
            {
                callArgumentStringBuilder.Append(parameterName);

                if (index < parameters.Count - 1)
                {
                    callArgumentStringBuilder.Append(", ");
                }

                index++;
            }

            var callArgumentString = callArgumentStringBuilder.ToString();

            writer.WriteLine($"{function.Name}({callArgumentString}){postCall};");
        }
        public static bool IsOperator(this CppFunction func) => func.Name.StartsWith("operator"); // TODO: regex?

        public static bool IsStatic(this CppFunction func) => func.StorageQualifier == CppStorageQualifier.Static;
 public static bool IsOperator(this CppFunction func) => func.Name.StartsWith("operator"); // TODO: regex?
Exemplo n.º 20
0
        private void DefineFunction(CodeType typeDecl, CppFunction func)
        {
            if (func.Name == "ArraySizeHelper")
            {
                return;
            }

            if (func.LinkageKind != CppLinkageKind.External)
            {
                throw new NotImplementedException();
            }

            TypeDesc retType = GetTypeDesc(func.ReturnType);
            var      fn      = new CodeMethod(func.Name);

            fn.RetVal = new CodeMethodParameter(null)
            {
                Type = ResolveCefType(retType.ToString())
            };
            fn.Attributes = CodeAttributes.Public | CodeAttributes.External | CodeAttributes.Unsafe | CodeAttributes.Static;
            if (func.CallingConvention == CppCallingConvention.C)
            {
                fn.CustomAttributes.AddDllImportfAttribute(CallingConvention.Cdecl);
            }
            else if (func.CallingConvention == CppCallingConvention.X86StdCall)
            {
                fn.CustomAttributes.AddDllImportfAttribute(CallingConvention.StdCall);
            }
            else
            {
                throw new NotImplementedException();
            }

            string filename = func.Span.Start.File;

            filename = Path.GetRelativePath(BaseDirectory, filename).Replace('\\', '/');
            fn.Comments.AddVSDocComment(func.Comment, "summary");
            fn.Comments.AddVSDocComment(string.Format("Defined in {0} as\n{1}", filename, func.ToString()), "remarks");

            CppContainerList <CppParameter> @params = func.Parameters;

            for (int i = 0; i < @params.Count; i++)
            {
                CppParameter arg = @params[i];

                var      param     = new CodeMethodParameter(arg.Name.EscapeName());
                TypeDesc paramType = GetTypeDesc(arg.Type);

                string argType = paramType.ToString();
                while (argType.StartsWith("const "))
                {
                    argType         = argType.Substring(6);
                    param.Direction = CodeMethodParameterDirection.In;
                }

                param.Type = ResolveCefType(argType);
                fn.Parameters.Add(param);
            }

            typeDecl.Members.Add(fn);
        }
 public static string GetParameterSignature(CppFunction cppFunction, bool canUseOut)
 {
     return(GetParameterSignature(cppFunction.Parameters, canUseOut));
 }
Exemplo n.º 22
0
 public CsFunction(CppFunction cppMethod) : base(cppMethod)
 {
 }
Exemplo n.º 23
0
 public CsFunction(CppFunction cppMethod) : base(cppMethod)
 {
 }
Exemplo n.º 24
0
 public PropertyInfo AsPropertyCandidate(CppFunction function)
 {
     return(_candidates.FirstOrDefault(c => c.GetterFunction == function || c.SetterFunction == function));
 }
Exemplo n.º 25
0
 public CsFunction(CppFunction cppFunction) : base(cppFunction)
 {
 }
Exemplo n.º 26
0
    public void Basic()
    {
        var config = new ConfigFile
        {
            Id        = nameof(Basic),
            Namespace = nameof(Basic),
            Includes  =
            {
                new IncludeRule
                {
                    Attach    = true,
                    File      = "func.h",
                    Namespace = nameof(Basic)
                }
            },
            Extension =
            {
                new CreateExtensionRule
                {
                    NewClass = $"{nameof(Basic)}.Functions",
                }
            },
            Bindings =
            {
                new BindRule("int", "System.Int32")
            },
            Mappings =
            {
                new MappingRule
                {
                    Function        = "Test",
                    FunctionDllName = "\"Test.dll\"",
                    Group           = $"{nameof(Basic)}.Functions"
                }
            }
        };

        var function = new CppFunction("Test")
        {
            ReturnValue = new CppReturnValue
            {
                TypeName = "int",
            }
        };

        var include = new CppInclude("func");

        var module = new CppModule("SharpGenTestModule");

        include.Add(function);
        module.Add(include);

        var(solution, _) = MapModel(module, config);

        Assert.Single(solution.EnumerateDescendants <CsGroup>());

        var group = solution.EnumerateDescendants <CsGroup>().First();

        Assert.Equal("Functions", group.Name);

        Assert.Single(group.Functions);

        var csFunc = group.Functions.First();

        Assert.Equal(TypeRegistry.Int32, csFunc.ReturnValue.PublicType);
        Assert.Empty(csFunc.Parameters);
        Assert.Equal(Visibility.Static, csFunc.Visibility & Visibility.Static);
    }
Exemplo n.º 27
0
        /// <summary>
        /// <param name="function">Function we about to generate [DllImport] for</param>
        /// <param name="cname">Exact C name</param>
        /// </summary>
        public static (string, string) GenerateMethodCSharp(CppFunction function, string cname)
        {
            var  dllImportSb     = new StringBuilder();
            var  apiDefinitionSb = new StringBuilder();
            var  apiImplSb       = new StringBuilder();
            bool castToBool      = false; // for cases when we a method returns non-blittable bools
            bool isStatic        = function.StorageQualifier == CppStorageQualifier.Static;

            List <CppParameter> parameters = function.Parameters;

            apiDefinitionSb.Append("public");
            if (isStatic)
            {
                apiDefinitionSb.Append(" static");
            }

            dllImportSb.Append(Tabs(2)).Append($"[DllImport({MainClassName}.NativeLib, CallingConvention=CallingConvention.Cdecl)]\n");
            dllImportSb.Append(Tabs(2)).Append("private static extern ");

            apiImplSb.Append(" => ");

            if (function.IsConstructor)
            {
                dllImportSb.Append("void*");
            }
            else
            {
                var returnTypeCs    = RemapTypeToCSharp(function.ReturnType.GetDisplayName());
                var returnTypeApiCs = returnTypeCs;
                if (returnTypeCs == "nint") // HACK - I want bindings to be Any CPU and don't want to expose IntPtr.
                {
                    returnTypeApiCs = returnTypeCs = "long";
                    apiImplSb.Append("(long)"); // cast to long
                }

                if (returnTypeCs == "bool")
                {
                    // bool is not blittable
                    castToBool   = true;
                    returnTypeCs = "byte";
                }

                dllImportSb.Append(returnTypeCs);
                apiDefinitionSb.Append(" ").Append(returnTypeApiCs);
            }

            dllImportSb.Append($" {cname}(");

            string apiName = ToCamelCase(function.Name);

            // ugly hacks
            if (isStatic && apiName == "IsObjectOrArray")
            {
                apiName = "IsObjectOrArrayStatic";
            }
            if (apiName == "GetType")
            {
                apiName = "GetTokenType";
            }

            if (function.IsConstructor)
            {
                if (function.Parent is CppClass cppClass)
                {
                    apiName = RemapTypeToCSharp(cppClass.Name);
                }
                else
                {
                    apiName = MainClassName; // Class for global functions
                }
            }

            apiDefinitionSb.Append($" {apiName}");

            bool convertedToProperty = false;

            if (function.Name.StartsWith("is") &&
                parameters.Count == 0 &&
                !function.IsConstructor)
            {
                convertedToProperty = true;
            }
            else
            {
                apiDefinitionSb.Append("(");
            }

            if (function.IsConstructor)
            {
                apiImplSb.Append($"this.Handle = {cname}(");
            }
            else
            {
                apiImplSb.Append($"{cname}(");
            }

            if (!function.IsConstructor && !isStatic)
            {
                dllImportSb.Append("void* target");
                apiImplSb.Append("this.Handle");

                if (parameters.Count > 0)
                {
                    dllImportSb.Append(", ");
                    apiImplSb.Append(", ");
                }
            }

            for (var i = 0; i < parameters.Count; i++)
            {
                CppParameter parameter = parameters[i];

                // TODO: extract default value if any

                bool isWrapper = false;
                var  ctype     = parameter.Type.GetDisplayName();
                if (_allClassNames.Any(c => ctype.Contains(c)))
                {
                    isWrapper = true;
                }

                var paramTypeNameCs    = RemapTypeToCSharp(parameter.Type.GetDisplayName());
                var paramTypePinvokeCs = paramTypeNameCs;

                if (paramTypeNameCs == "nint")
                {
                    paramTypeNameCs    = "long";
                    paramTypePinvokeCs = "IntPtr";
                    apiImplSb.Append("(IntPtr)"); // cast to IntPtr
                }


                dllImportSb.Append(isWrapper ? "void*" : paramTypePinvokeCs);
                dllImportSb.Append(" ");
                dllImportSb.Append(parameter.Name);

                apiDefinitionSb.Append(paramTypeNameCs);
                apiDefinitionSb.Append(" ");
                apiDefinitionSb.Append(parameter.Name);

                apiImplSb.Append(parameter.Name);
                if (isWrapper)
                {
                    apiImplSb.Append(".Handle");
                }

                if (i < parameters.Count - 1)
                {
                    dllImportSb.Append(", ");
                    apiDefinitionSb.Append(", ");
                    apiImplSb.Append(", ");
                }
            }

            dllImportSb.Append(");");
            if (!convertedToProperty)
            {
                apiDefinitionSb.Append(")");
            }

            if (castToBool)
            {
                apiImplSb.AppendLine(") > 0;");
            }
            else
            {
                apiImplSb.AppendLine(");");
            }

            return(dllImportSb.ToString(), $"{GenerateCommentsSummary(2, function.Comment)}{Tabs(2)}{apiDefinitionSb}{apiImplSb}");
        }
Exemplo n.º 28
0
        private static void GenerateCommands(CppCompilation compilation, string outputPath)
        {
            // Generate Functions
            using var writer = new CodeWriter(Path.Combine(outputPath, "Commands.cs"),
                                              "System",
                                              "Vortice.Mathematics"
                                              );

            var commands         = new Dictionary <string, CppFunction>();
            var instanceCommands = new Dictionary <string, CppFunction>();
            var deviceCommands   = new Dictionary <string, CppFunction>();

            foreach (CppFunction?cppFunction in compilation.Functions)
            {
                string?returnType      = GetCsTypeName(cppFunction.ReturnType, false);
                bool   canUseOut       = s_outReturnFunctions.Contains(cppFunction.Name);
                string?csName          = cppFunction.Name;
                string?argumentsString = GetParameterSignature(cppFunction, canUseOut);

                commands.Add(csName, cppFunction);

                if (cppFunction.Parameters.Count > 0)
                {
                    var firstParameter = cppFunction.Parameters[0];
                    if (firstParameter.Type is CppTypedef typedef)
                    {
                        if (typedef.Name == "VkInstance" ||
                            typedef.Name == "VkPhysicalDevice" ||
                            IsInstanceFunction(cppFunction.Name))
                        {
                            instanceCommands.Add(csName, cppFunction);
                        }
                        else
                        {
                            deviceCommands.Add(csName, cppFunction);
                        }
                    }
                }
            }

            using (writer.PushBlock($"unsafe partial class Vulkan"))
            {
                foreach (KeyValuePair <string, CppFunction> command in commands)
                {
                    CppFunction cppFunction = command.Value;

                    if (cppFunction.Name == "vkCmdSetBlendConstants")
                    {
                    }

                    writer.WriteLine($"private static IntPtr {command.Key}_ptr;");
                    writer.WriteLine($"[Calli]");

                    var  returnType      = GetCsTypeName(cppFunction.ReturnType, false);
                    bool canUseOut       = s_outReturnFunctions.Contains(cppFunction.Name);
                    var  argumentsString = GetParameterSignature(cppFunction, canUseOut);

                    using (writer.PushBlock($"public static {returnType} {cppFunction.Name}({argumentsString})"))
                    {
                        writer.WriteLine("throw new NotImplementedException();");
                    }
                    writer.WriteLine();
                }

                WriteCommands(writer, "GenLoadInstance", instanceCommands);
                WriteCommands(writer, "GenLoadDevice", deviceCommands);
            }
        }
Exemplo n.º 29
0
        /// <param name="dllImportPath">will be used as the first argument in [DllImport]. Can be a path to some constant</param>
        /// <param name="generateCForGlobalFunctions">sometimes global functions are ready to be pinvoked as is</param>
        public static void Generate(TypeMapper mapper, TemplateManager templateManager, string @namespace, string dllImportPath, string outCFile, string outCsFile, bool generateCForGlobalFunctions = true)
        {
            var csFileSb = new StringBuilder();
            var cFileSb  = new StringBuilder();

            foreach (CppClassContainer cppClass in mapper.GetAllClasses())
            {
                var csClassSb = new StringBuilder();
                List <CppFunction> allFunctions = cppClass.Functions;
                for (int i = 0; i < allFunctions.Count; i++)
                {
                    CppFunction function = allFunctions[i];

                    if (!mapper.IsSupported(function.ReturnType.GetDisplayName()) ||
                        !function.Parameters.All(p => mapper.IsSupported(p.Type.GetDisplayName())) ||
                        function.IsOperator())
                    {
                        Logger.LogWarning($"Ignoring {function.Name}");
                        // we can't bind this method (yet)
                        continue;
                    }

                    // Type_MethodName1
                    string flatFunctionName = $"{cppClass.Name}_{function.Name}{i}";
                    if (!generateCForGlobalFunctions)
                    {
                        flatFunctionName = function.Name; // we are going to pinvoke it directly
                    }
                    var cfunctionWriter = new FunctionWriter();
                    var dllImportWriter = new FunctionWriter();
                    // TODO: apiFunctionWriter = new FunctionWriter();

                    dllImportWriter.Attribute($"[DllImport({dllImportPath}, CallingConvention = CallingConvention.Cdecl)]")
                    .Private().Static().Extern();

                    if (function.IsConstructor)
                    {
                        cfunctionWriter.ReturnType(cppClass.Class.GetFullTypeName() + "*", "EXPORTS");
                        dllImportWriter.ReturnType(nameof(IntPtr));
                    }
                    else
                    {
                        var funcReturnType = function.ReturnType.GetFullTypeName();
                        cfunctionWriter.ReturnType(funcReturnType, "EXPORTS");
                        dllImportWriter.ReturnType(mapper.MapToManagedType(funcReturnType));
                    }

                    // PS: should we generate C for global functions (we currently do)? probably it should be optional

                    cfunctionWriter.MethodName(flatFunctionName);
                    dllImportWriter.MethodName(flatFunctionName);

                    if (!function.IsConstructor &&
                        !function.IsStatic() &&
                        !cppClass.IsGlobal)
                    {
                        // all instance methods will have "this" as the first argument
                        cfunctionWriter.Parameter(cppClass.Class.GetFullTypeName() + "*", "target");
                        dllImportWriter.Parameter(nameof(IntPtr), "target");
                    }

                    foreach (var parameter in function.Parameters)
                    {
                        cfunctionWriter.Parameter(
                            parameter.Type.GetDisplayName(),
                            parameter.Name);

                        dllImportWriter.Parameter(
                            mapper.MapToManagedType(parameter.Type.GetDisplayName()),
                            mapper.EscapeVariableName(parameter.Name));
                    }

                    // append "return" if needed
                    cfunctionWriter.BodyStart();

                    if (cppClass.IsGlobal)
                    {
                        // GlobalMethod
                        cfunctionWriter.BodyCallMethod(function.Name);
                    }
                    else if (!function.IsConstructor && !function.IsStatic())
                    {
                        // target->InstanceMethod
                        cfunctionWriter.BodyCallMethod($"target->{function.Name}");
                    }
                    else if (function.IsStatic())
                    {
                        // Class1::StaticMethod
                        cfunctionWriter.BodyCallMethod(cppClass.Class.GetFullTypeName() + "::" + function.Name);
                    }
                    else
                    {
                        // new Class1
                        cfunctionWriter.BodyCallMethod($"new {cppClass.Class.GetFullTypeName()}");
                    }


                    foreach (var parameter in function.Parameters)
                    {
                        cfunctionWriter.PassParameter(parameter.Name);
                    }

                    csClassSb.AppendLine(dllImportWriter.BuildWithoutBody().Tabify(2));
                    csClassSb.AppendLine();

                    cFileSb.AppendLine(cfunctionWriter.Build());
                    cFileSb.AppendLine();
                }

                if (cppClass.IsGlobal && generateCForGlobalFunctions)
                {
                    csFileSb.Append(templateManager.CSharpGlobalClass(csClassSb.ToString(), dllImportPath));
                }
                else if (!cppClass.IsGlobal)
                {
                    csFileSb.Append(templateManager.CSharpClass(cppClass.Name, cppClass.Name, csClassSb.ToString(), dllImportPath));
                }
            }

            File.WriteAllText(outCFile, templateManager.CHeader() + cFileSb);
            File.WriteAllText(outCsFile, templateManager.CSharpHeader(@namespace, csFileSb.ToString()));
        }