コード例 #1
0
ファイル: CodeGen_Function.cs プロジェクト: Macad3D/Macad3D
        //--------------------------------------------------------------------------------------------------

        bool GenerateFunctionPostNativeCall(StringWriter wf, Definitions.FunctionDefintion fd, int maxParameterCount)
        {
            // Resolve parameter list
            int count = 0;

            foreach (var pd in fd.Parameters)
            {
                count++;
                if (count > maxParameterCount)
                {
                    break;
                }

                if (pd.Type.IsKnownType && pd.Type.KnownTypeDef.Type == Definitions.KnownTypes.Standard_CString)
                {
                    wf.WriteLine($"\tMarshal::FreeHGlobal((System::IntPtr)(void*)sz_{pd.Name});");
                }
                else if (pd.Type.IsHandle && pd.Type.IsReference)
                {
                    // References to handles may receive another encapsulated object.
                    wf.WriteLine($"\t{pd.Name}->NativeInstance = h_{pd.Name}.get();");
                }
            }

            // Return type
            if ((!fd.Type.IsVoid || fd.Type.IsVoidPointer) && !fd.IsConstructor && !fd.Type.IsValueType(fd.Class))
            {
                // Known type
                if (fd.Type.IsKnownType && fd.Type.KnownTypeDef.Type != Definitions.KnownTypes.WrappedClass)
                {
                    switch (fd.Type.KnownTypeDef.Type)
                    {
                    case Definitions.KnownTypes.Standard_CString:
                        wf.WriteLine($"\treturn gcnew System::String(_result);");
                        break;

                    case Definitions.KnownTypes.Standard_ExtString:
                        wf.WriteLine($"\treturn gcnew System::String((const wchar_t *)_result);");
                        break;

                    default:
                        return(false);
                    }
                }
                else
                {
                    // Generic class or handle type
                    wf.WriteLine(fd.Type.IsHandle
                                     ? $"\t return _result.IsNull() ? nullptr : {fd.Type.Fqn(fd.Class)}::CreateDowncasted( _result.get());"
                                     : $"\t return _result==nullptr ? nullptr : gcnew {fd.Type.Fqn(fd.Class)}(_result);");
                }
            }

            return(true);
        }
コード例 #2
0
        void GenerateFunctionDeclaration(StringWriter w, Definitions.FunctionDefintion fd, int maxParameterCount)
        {
            StringWriter wf = new StringWriter();

            if (!GenerateFunctionDecl(wf, fd, true, maxParameterCount))
            {
                w.Write("/* Method skipped due to unknown mapping: {0} {1}(", fd.Type.Name, fd.Name);
                foreach (var pd in fd.Parameters)
                {
                    w.Write("{0} {1}, ", pd.Type.Name, pd.Name);
                }
                w.WriteLine(") */");
            }
            else
            {
                w.Write(wf.ToString());
            }
        }
コード例 #3
0
        //--------------------------------------------------------------------------------------------------

        void _AddFunction(Definitions.ClassDefinition klass, CastXml.Method method, int funcType)
        {
            var fName   = funcType == 0 ? method.name : klass.Name;
            var logName = klass.Name + "::" + fName;

            if (Configuration.Ignore.Contains(klass.Name + "::" + fName) || Configuration.Ignore.Contains("*::" + fName))
            {
                Logger.WriteLine(true, "Function " + logName + " ignored by definition.");
                return;
            }

            if (fName.StartsWith("_CSFDB_"))
            {
                Logger.WriteLine(true, "Function " + logName + " ignored because it begins with _CSFDB_");
                return;
            }

            // Create function
            var f = new Definitions.FunctionDefintion()
            {
                Class         = klass,
                Name          = fName,
                Type          = (funcType == 0) ? _GetTypeDefinition(method.returns) : _VoidTypeDefinition,
                IsStatic      = method.IsStatic,
                IsPublic      = method.IsPublic,
                IsConstructor = funcType == 1,
                IsDestructor  = funcType == 2,
                IsOperator    = false,
                IsTemplate    = fName.Contains('<'),
                IsAbstract    = method.IsPureVirtual,
            };

            if (f.Type == null)
            {
                Logger.WriteLine(true, string.Format("\tFunction " + logName + " ignored because of an unknown return type (FunctionType?)."));
                return;
            }

            Logger.WriteLine(true, string.Format("\tRelevant function: [{0}] {1} type='{2}'", method.id, fName, f.Type.Name));

            // Get parameters
            int unnamedCount = 1;

            if (method.Argument != null)
            {
                foreach (var p in method.Argument)
                {
                    var fp = new Definitions.ParameterDefinition
                    {
                        Type = _GetTypeDefinition(p.type)
                    };

                    if (fp.Type == null)
                    {
                        Logger.WriteLine(true, string.Format("\tFunction " + logName + " ignored because of an unknown parameter type (FunctionType?)."));
                        return;
                    }

                    if (string.IsNullOrEmpty(p.name))
                    {
                        fp.Name = $"parameter{unnamedCount}";
                        unnamedCount++;
                    }
                    else
                    {
                        fp.Name = p.name;
                    }

                    if (Configuration.NameReplacements.ContainsKey(fp.Name))
                    {
                        fp.Name = Configuration.NameReplacements[fp.Name];
                    }

                    if (!string.IsNullOrEmpty(p.@default))
                    {
                        fp.Default = [email protected](TrimChars);

                        // Make sure any type is interpreted as native, not wrapped
                        if (fp.Default.StartsWith("opencascade::handle<"))
                        {
                            fp.Default = fp.Default.Insert(20, "::");
                        }
                        else if (fp.Default.EndsWith("()")) // Constructor
                        {
                            fp.Default = "::" + fp.Default;
                        }

                        fp.HasDefault = true;
                    }

                    Logger.WriteLine(true, $"\t\tRelevant parameter: {fp.Name} type='{fp.Type.Name}' default='{fp.Default}'");

                    f.Parameters.Add(fp);
                }

                if (f.Parameters.All(pd => pd.Type.IsVoid && !pd.Type.IsPointer))
                {
                    // Only one void parameter, thats equivalent to no parameter
                    Logger.WriteLine(true, "\t\tFunction " + logName + " cleared all parameters because it has only one of type void.");
                    f.Parameters.Clear();
                }
            }

            if (!klass.Functions.Any(other => f.IsEqual(other)))
            {
                klass.Functions.Add(f);
            }
        }
コード例 #4
0
        //--------------------------------------------------------------------------------------------------

        bool GenerateFunctionDecl(StringWriter w, Definitions.FunctionDefintion fd, bool isHeader, int maxParameterCount)
        {
            if (fd.IsTemplate)
            {
                w.Write($"generic <typename {fd.TemplateName}> ");
            }

            if (isHeader && ((fd.IsStatic) || (fd.IsOperator)))
            {
                w.Write("static ");
            }

            // Write return type, if not constructor
            if ((!fd.IsConstructor) && (!fd.IsDestructor))
            {
                if (!GenerateTypeDecl(w, fd.Type, fd.Class, true))
                {
                    return(false);
                }
            }

            if (!isHeader)
            {
                w.Write($"{fd.Class.Fqn}::");
            }

            if (Configuration.NameReplacements.ContainsKey(fd.Name))
            {
                w.Write(Configuration.NameReplacements[fd.Name]);
            }
            else
            {
                w.Write(fd.Name);
            }

            w.Write("(");

            // Write all parameters
            bool isFirst = true;

            // Write this as operator param
            if (fd.IsOperator)
            {
                w.Write($"{fd.Class.Fqn}^ This");
                isFirst = false;
            }

            // Write all other params
            int count = 0;

            foreach (var pd in fd.Parameters)
            {
                count++;
                if (count > maxParameterCount)
                {
                    break;
                }

                if (isFirst)
                {
                    isFirst = false;
                }
                else
                {
                    w.Write(", ");
                }

                if (!GenerateTypeDecl(w, pd.Type, fd.Class, false))
                {
                    return(false);
                }

                w.Write(pd.Name);
            }

            w.Write(")");

            if (isHeader)
            {
                w.Write(";");
            }
            w.WriteLine();
            return(true);
        }
コード例 #5
0
        //--------------------------------------------------------------------------------------------------

        bool GenerateFunctionNativeCallParameters(StringWriter wf, Definitions.FunctionDefintion fd, int maxParameterCount)
        {
            // Write parameter list
            bool isFirst = true;
            int  count   = 0;

            foreach (var pd in fd.Parameters)
            {
                if (isFirst)
                {
                    isFirst = false;
                }
                else
                {
                    wf.Write(", ");
                }

                count++;
                if (count > maxParameterCount)
                {
                    // Default parameter
                    wf.Write(pd.NativeDefault);
                    continue;
                }

                if (pd.Type.IsUnknown)
                {
                    return(false);
                }

                if (pd.Type.IsValueType(fd.Class))
                {
                    if (pd.Type.IsVoidPointer)
                    {
                        wf.Write(pd.Name + ".ToPointer()");
                    }
                    else if (pd.Type.IsReference)
                    {
                        // Reference to values need temp variable
                        wf.Write("*({0}*)pp_{1}", pd.Type.IsKnownType ? pd.Type.KnownTypeDef.NativeFqn : pd.Type.Native(fd.Class), pd.Name);
                    }
                    else if (pd.Type.IsPointer)
                    {
                        // Pointer to values need temp variable
                        wf.Write("({0}*)pp_{1}", pd.Type.IsKnownType ? pd.Type.KnownTypeDef.NativeFqn : pd.Type.Native(fd.Class), pd.Name);
                    }
                    else
                    {
                        if (pd.Type.IsEnum(fd.Class))
                        {
                            // Typecast enum to native type
                            wf.Write($"({pd.Type.Native(fd.Class)}){pd.Name}");
                        }
                        else
                        {
                            // Known class
                            if (pd.Type.IsKnownType)
                            {
                                switch (pd.Type.KnownTypeDef.Type)
                                {
                                case Definitions.KnownTypes.Enum:
                                    wf.Write($"({pd.Type.KnownTypeDef.NativeFqn})");
                                    break;

                                case Definitions.KnownTypes.WrappedStruct:
                                    wf.Write($"*({pd.Type.KnownTypeDef.NativeFqn}*)pp_");
                                    break;
                                }
                            }

                            // Just write out name
                            wf.Write(pd.Name);
                        }
                    }
                }
                else // isValueType
                {
                    // Class types
                    var klass = Definitions.ClassItems.FirstOrDefault(cd => cd.Name.Equals(pd.Type.Name));
                    if (klass != null)
                    {
                        if (klass.IsTransient && pd.Type.IsHandle)
                        {
                            if (pd.Type.IsReference)
                            {
                                // prepared copy of the handle
                                wf.Write($"h_{pd.Name}");
                            }
                            else
                            {
                                // temp handle generated inplace
                                wf.Write($"{klass.NativeHandle}({pd.Name}->NativeInstance)");
                            }
                        }
                        else
                        {
                            // Wrapped class
                            wf.Write(pd.Type.IsPointer || pd.Type.IsHandle
                                         ? $"({klass.Native}*){pd.Name}->NativeInstance"
                                         : $"*({klass.Native}*){pd.Name}->NativeInstance");
                        }
                    }
                    else
                    {
                        // Known class
                        if (pd.Type.IsKnownType)
                        {
                            switch (pd.Type.KnownTypeDef.Type)
                            {
                            case Definitions.KnownTypes.Standard_CString:
                                wf.Write($"sz_{pd.Name}");
                                break;

                            case Definitions.KnownTypes.Standard_ExtString:
                                wf.Write($"(Standard_ExtString)pp_{pd.Name}");
                                break;

                            default:
                                return(false);
                            }
                        }
                        else
                        {
                            wf.Write(pd.Name);
                        }
                    }
                }
            }

            return(true);
        }
コード例 #6
0
        //--------------------------------------------------------------------------------------------------

        void GenerateFunctionSource(StringWriter w, Definitions.FunctionDefintion fd, int maxParameterCount)
        {
            StringWriter wfd = new StringWriter();

            if (!GenerateFunctionDecl(wfd, fd, false, maxParameterCount))
            {
                return;
            }
            w.Write(wfd.ToString());

            if (fd.IsConstructor)
            {
                w.WriteLine($"\t: {fd.Class.SuperClassFqn}(BaseClass::InitMode::Uninitialized)");
            }

            w.WriteLine("{");

            // Check if we have an unexported function
            var ft = string.Join(",", fd.Parameters.Select(pd => pd.Type.Name).ToArray());

            if (Configuration.MissingExports.Contains($"{fd.Class.Name}::{fd.Name}({ft})"))
            {
                w.WriteLine("\tthrow gcnew System::NotImplementedException(\"Unresolved external symbol\");");
                w.WriteLine("}");
                w.WriteLine();
                return;
            }

            // Check if we have a default constructor in an abstract class
            if ((fd.Class.IsAbstract || fd.Class.HasAbstractFunctions) && fd.IsConstructor)// && fd.Parameters.Count == 0)
            {
                // Write empty constructor
                w.WriteLine("\tthrow gcnew System::NotImplementedException(\"Native class is abstract\");");
                w.WriteLine("}");
                w.WriteLine();
                return;
            }

            // Check if we have a result which cannot be wrapped
            if (fd.Type.IsPointer &&
                (fd.Type.IsHandle ||
                 fd.Type.IsKnownType && ((fd.Type.KnownTypeDef.Type == Definitions.KnownTypes.Integer) || (fd.Type.KnownTypeDef.Type == Definitions.KnownTypes.Double))))
            {
                w.WriteLine("\tthrow gcnew System::NotImplementedException(\"Native class returns pointer to integer/double/handle.\");");
                w.WriteLine("}");
                w.WriteLine();
                return;
            }

            bool         valid = false;
            StringWriter wf    = new StringWriter();

            if (GenerateFunctionPreNativeCall(wf, fd, maxParameterCount))
            {
                if (GenerateFunctionNativeCall(wf, fd, maxParameterCount))
                {
                    if (GenerateFunctionPostNativeCall(wf, fd, maxParameterCount))
                    {
                        valid = true;
                    }
                }
            }

            if (!valid)
            {
                w.WriteLine("\tthrow gcnew System::NotImplementedException();");
            }
            else
            {
                w.Write(wf.ToString());
            }
            w.WriteLine("}");
            w.WriteLine();
        }
コード例 #7
0
        //--------------------------------------------------------------------------------------------------

        bool GenerateFunctionNativeCall(StringWriter wf, Definitions.FunctionDefintion fd, int maxParameterCount)
        {
            if (Configuration.UnknownTypes.Contains(fd.Type.Name))
            {
                return(false);
            }

            wf.Write("\t");

            string closing = ")";

            // If the return value is a value type: return xxx
            if (!fd.IsConstructor && (!fd.Type.IsVoid || fd.Type.IsVoidPointer))
            {
                if (fd.Type.IsValueType(fd.Class))
                {
                    wf.Write("return ");
                    if (fd.Type.IsVoidPointer)
                    {
                        wf.Write("System::IntPtr("); //wf.Write("gcnew System::IntPtr(");
                        closing += ")";
                    }
                    else if ((fd.Type.IsEnum(fd.Class)) ||
                             (fd.Type.IsKnownType && (fd.Type.KnownTypeDef.Type == Definitions.KnownTypes.Enum)))
                    {
                        // Typecast enum to managed type
                        wf.Write("(" + fd.Type.Fqn(fd.Class) + ")");
                    }
                    else if (fd.Type.IsKnownType && fd.Type.KnownTypeDef.Type == Definitions.KnownTypes.WrappedStruct)
                    {
                        // Crate new value type
                        wf.Write(fd.Type.KnownTypeDef.Fqn + "(");
                        closing += ")";
                    }
                }
                else
                {
                    // Is a class type, so use the prepared native pointer
                    if (fd.Type.IsHandle)
                    {
                        //  Handles
                        wf.Write("_result = ");
                    }
                    else
                    {
                        // Pointers
                        if (fd.Type.IsPointer) // (fd.Type.IsConst) &&
                        {
                            wf.Write($"_result = ({fd.Type.Native(fd.Class)}*)");
                        }
                        else
                        {
                            if (fd.Type.IsKnownType && ((fd.Type.KnownTypeDef.Type == Definitions.KnownTypes.Standard_CString) || (fd.Type.KnownTypeDef.Type == Definitions.KnownTypes.Standard_ExtString)))
                            {
                                wf.Write("_result = ");
                            }
                            else
                            {
                                // Create pointer to instance
                                wf.Write("*_result = ");
                                if (fd.Type.IsConst)
                                {
                                    // Get rid of 'const' qualifier
                                    wf.Write($" ({fd.Type.Native(fd.Class)})");
                                }
                            }
                        }
                    }
                }
            }

            // Call to static method
            if (fd.IsStatic)
            {
                wf.Write($"{fd.Class.Native}::{fd.Name}(");
            }
            else
            {
                // Call to constructor
                if (fd.IsConstructor)
                {
                    if (fd.Class.IsTransient)
                    {
                        wf.Write($"NativeInstance = new {fd.Class.Native}(");
                    }
                    else
                    {
                        wf.Write($"_NativeInstance = new {fd.Class.Native}(");
                    }
                }
                else if (fd.IsOperator)
                {
                    // Call to operator
                    wf.Write($"_NativeInstance->{fd.Name}(");
                }
                else
                {
                    // Call to non-static method
                    wf.Write($"(({fd.Class.Native}*)_NativeInstance)->{fd.Name}(");
                }
            }

            // Write parameter list
            if (!GenerateFunctionNativeCallParameters(wf, fd, maxParameterCount))
            {
                return(false);
            }

            // Close function parameter list and close statement
            wf.Write(closing);

            wf.WriteLine(";");

            return(true);
        }
コード例 #8
0
        //--------------------------------------------------------------------------------------------------

        bool GenerateFunctionPreNativeCall(StringWriter wf, Definitions.FunctionDefintion fd, int maxParameterCount)
        {
            // Prepare parameter list
            int count = 0;

            foreach (var pd in fd.Parameters)
            {
                count++;
                if (count > maxParameterCount)
                {
                    break;
                }

                if (pd.Type.IsKnownType && pd.Type.KnownTypeDef.Type == Definitions.KnownTypes.Standard_CString)
                {
                    wf.WriteLine($"\tconst char* sz_{pd.Name} = (char*)(void*)Marshal::StringToHGlobalAnsi({pd.Name});");
                }
                else if (pd.Type.IsKnownType && pd.Type.KnownTypeDef.Type == Definitions.KnownTypes.Standard_ExtString)
                {
                    wf.WriteLine($"\tpin_ptr<const wchar_t> pp_{pd.Name} = PtrToStringChars({pd.Name});");
                }
                else if (pd.Type.IsValueType(fd.Class)
                         // For wrapped struct always, for other value types only if they are given as reference
                         && (pd.Type.IsReference || pd.Type.IsPointer || (pd.Type.IsKnownType && pd.Type.KnownTypeDef.Type == Definitions.KnownTypes.WrappedStruct)) &&
                         !pd.Type.IsVoid)
                {
                    wf.WriteLine("\tpin_ptr<{0}> pp_{1} = &{1};",
                                 pd.Type.IsKnownType ? pd.Type.KnownTypeDef.Fqn : pd.Type.Fqn(fd.Class), pd.Name);
                }
                else if (pd.Type.IsHandle && pd.Type.IsReference)
                {
                    // References to handles may receive another encapsulated object.
                    wf.WriteLine($"\t{pd.Type.NativeHandle} h_{pd.Name} = {pd.Name}->NativeInstance;");
                }
            }

            // Prepare temp return class
            if (!fd.IsConstructor && !fd.Type.IsVoid)
            {
                if (!fd.Type.IsValueType(fd.Class))
                {
                    // If return value is class type, prepare new native pointer
                    if (fd.Type.IsKnownType)
                    {
                        switch (fd.Type.KnownTypeDef.Type)
                        {
                        case Definitions.KnownTypes.Standard_CString:
                            wf.WriteLine("\tStandard_CString _result;");
                            break;

                        case Definitions.KnownTypes.Standard_ExtString:
                            wf.WriteLine("\tStandard_ExtString _result;");
                            break;
                        }
                        return(true);
                    }

                    // Standard class type
                    if (fd.Type.IsPointer)
                    {
                        wf.WriteLine($"\t{fd.Type.Native(fd.Class)}* _result;");// = new " + fd.Type.Native + "();");
                    }
                    else if (fd.Type.IsHandle)
                    {
                        wf.WriteLine($"\t{fd.Type.NativeHandle} _result;");
                    }
                    else
                    {
                        // Find class
                        var klass = Definitions.ClassItems.FirstOrDefault(cd => cd.Name.Equals(fd.Type.Name));
                        if (fd.IsConstructor)
                        {
                            wf.WriteLine($"\t{fd.Type.Native(fd.Class)}* _result;");
                            return(true);
                        }

                        // Check if there has any constructors we can fill with value types
                        if ((klass == null) || (klass.HasAbstractFunctions) || (klass.IsAbstract))
                        {
                            return(false);
                        }
                        var constructor = klass.Functions.FirstOrDefault(kfd => kfd.IsConstructor && kfd.Parameters.All(pd => pd.HasDefault || pd.Type.IsValueType(fd.Class)));
                        if (constructor == null)
                        {
                            return(false);
                        }

                        // Write out initialization values for constructor
                        bool isFirst = true;
                        wf.Write($"\t{fd.Type.Native(fd.Class)}* _result = new {fd.Type.Native(fd.Class)}(");
                        foreach (var cpd in constructor.Parameters)
                        {
                            if (!isFirst)
                            {
                                wf.Write(", ");
                            }
                            isFirst = false;

                            var initValue = cpd.HasDefault ? cpd.NativeDefault : cpd.Type.GetInitValue();
                            if (string.IsNullOrEmpty(initValue))
                            {
                                return(false);
                            }

                            wf.Write(initValue);
                        }
                        wf.WriteLine(");");
                    }
                }
            }

            return(true);
        }