Ejemplo n.º 1
0
void CSModuleWriter::GenerateManagedModuleClass(String& sourceOut)
{
    Indent();

    String source;
    String line = ToString("public static partial class %sModule\n", module_->GetName().CString());

    source += IndentLine(line);

    source += IndentLine("{\n");

    Indent();

    source += IndentLine("public static void Initialize()\n");

    source += IndentLine("{\n");

    Indent();

    Vector<SharedPtr<JSBClass>> classes = module_->classes_.Values();

    for (unsigned i = 0; i < classes.Size(); i++)
    {
        JSBClass* klass = classes.At(i);
        JSBPackage* package = module_->GetPackage();

        if (klass->IsNumberArray() || klass->IsAbstract())
            continue;

        line = ToString("NativeCore.RegisterNativeType(typeof(%s));\n", klass->GetName().CString());

        source += IndentLine(line);

        line = ToString("NativeCore.nativeClassIDToManagedConstructor [ %s.csb_%s_%s_GetClassIDStatic ()] = (IntPtr x) => {\n",
                        klass->GetName().CString(), package->GetName().CString(), klass->GetName().CString());

        source += IndentLine(line);

        Indent();

        source += IndentLine(ToString("return new %s (x);\n", klass->GetName().CString()));

        Dedent();

        source += IndentLine("};\n");

    }

    Dedent();

    source += IndentLine("}\n");

    Dedent();

    source += IndentLine("}\n");

    sourceOut += source;

    Dedent();
}
Ejemplo n.º 2
0
void CSFunctionWriter::WriteManagedConstructor(String& source)
{
    JSBClass* klass = function_->GetClass();
    JSBPackage* package = klass->GetPackage();

    if (klass->GetName() == "RefCounted")
        return;

    // wrapping constructor

    String line;

    line = ToString("public %s (IntPtr native) : base (native)\n", klass->GetName().CString());
    source += IndentLine(line);
    source += IndentLine("{\n");
    source += IndentLine("}\n\n");

    String sig;
    GenManagedFunctionParameters(sig);

    line = ToString("public %s (%s)\n", klass->GetName().CString(), sig.CString());

    source += IndentLine(line);

    source += IndentLine("{\n");

    Indent();

    WriteDefaultStructParameters(source);

    line = ToString("if (typeof(%s) == this.GetType()", klass->GetName().CString());
    line += ToString(" || (this.GetType().BaseType == typeof(%s) && !NativeCore.GetNativeType(this.GetType())))\n", klass->GetName().CString());

    source += IndentLine(line);

    source += IndentLine("{\n");

    Indent();

    String callSig;
    GenPInvokeCallParameters(callSig);

    line = ToString("nativeInstance = NativeCore.RegisterNative (csb_%s_%s_Constructor(%s), this);\n",
                     package->GetName().CString(), klass->GetName().CString(), callSig.CString());

    source += IndentLine(line);

    Dedent();

    source += IndentLine("}\n");

    Dedent();

    source += IndentLine("}\n");
}
Ejemplo n.º 3
0
void CSClassWriter::WriteManagedProperties(String& sourceOut)
{
    String source;

    if (klass_->HasProperties())
    {
        Vector<String> pnames;
        klass_->GetPropertyNames(pnames);

        for (unsigned j = 0; j < pnames.Size(); j++)
        {
            JSBProperty* prop = klass_->GetProperty(pnames[j]);

            JSBFunctionType* fType = NULL;
            JSBFunctionType* getType = NULL;
            JSBFunctionType* setType = NULL;

            if (CSTypeHelper::OmitFunction(prop->getter_) || CSTypeHelper::OmitFunction(prop->setter_))
                continue;

            if (prop->getter_ && !prop->getter_->Skip())
            {
                fType = getType = prop->getter_->GetReturnType();
            }
            if (prop->setter_ && !prop->setter_->Skip())
            {
                setType = prop->setter_->GetParameters()[0];

                if (!fType)
                    fType = setType;
                else if (fType->type_->ToString() != setType->type_->ToString())
                    continue;
            }

            if (!fType)
                continue;

            String line = klass_->IsInterface() ? "" : "public ";

            JSBClass* baseClass = klass_->GetBaseClass();
            if (baseClass)
            {
                if (baseClass->MatchProperty(prop, true))
                {
                    // always new so we don't have to deal with virtual/override on properties
                    line += "new ";
                }
            }

            String type = CSTypeHelper::GetManagedTypeString(fType, false);
            line += ToString("%s %s\n", type.CString(), prop->name_.CString());
            source += IndentLine(line);
            source += IndentLine("{\n");

            Indent();

            if (prop->getter_)
            {
                if (klass_->IsInterface())
                {
                    source += IndentLine("get;\n");
                }
                else
                {
                    source += IndentLine("get\n");
                    source += IndentLine("{\n");

                    Indent();

                    source += IndentLine(ToString("return %s();\n", prop->getter_->GetName().CString()));

                    Dedent();

                    source += IndentLine("}\n");
                }
            }

            if (prop->setter_)
            {
                if (klass_->IsInterface())
                {
                    source += IndentLine("set;\n");
                }
                else
                {
                    source += IndentLine("set\n");
                    source += IndentLine("{\n");

                    Indent();

                    source += IndentLine(ToString("%s(value);\n", prop->setter_->GetName().CString()));

                    Dedent();

                    source += IndentLine("}\n");

                }

            }

            Dedent();

            source += IndentLine("}\n\n");
        }

    }

    sourceOut += source;

}
Ejemplo n.º 4
0
void CSClassWriter::GenerateManagedSource(String& sourceOut)
{
    String source = "";

    if (klass_->IsNumberArray())
        return;

    Indent();

    source += "\n";
    String line;

    if (klass_->GetDocString().Length())
    {
        // monodocer -assembly:NETCore.dll -path:en -pretty
        // mdoc export-html -o htmldocs en
        source += IndentLine("/// <summary>\n");
        if (klass_->GetDocString().Contains('\n'))
            source += IndentLine("/* " + klass_->GetDocString() + "*/\n");
        else
            source += IndentLine("/// " + klass_->GetDocString() + "\n");

        source += IndentLine("/// </summary>\n");
    }

    if (klass_->GetBaseClass())
    {

        String baseString = klass_->GetBaseClass()->GetName();

        const PODVector<JSBClass*>& interfaces = klass_->GetInterfaces();

        if (interfaces.Size())
        {
            StringVector baseStrings;
            baseStrings.Push(baseString);
            for (unsigned i = 0; i < interfaces.Size(); i++)
            {
                baseStrings.Push(interfaces.At(i)->GetName());
            }

            baseString = String::Joined(baseStrings, ",");
        }

        line = ToString("public partial class %s%s : %s\n", klass_->GetName().CString(), klass_->IsGeneric() ? "<T>" : "", baseString.CString());
    }
    else
    {
        String classString = "class";

        if (klass_->IsInterface())
            classString = "interface";

        line = ToString("public partial %s %s%s\n", classString.CString(), klass_->GetName().CString(), klass_->IsGeneric() ? "<T>" : "");
    }


    source += IndentLine(line);
    source += IndentLine("{\n");

    Indent();

    WriteManagedProperties(source);

    JSBPackage* package = klass_->GetPackage();

    // CoreCLR has pinvoke security demand code commented out, so we do not (currently) need this optimization:
    // https://github.com/dotnet/coreclr/issues/1605
    // line = "[SuppressUnmanagedCodeSecurity]\n";
    // source += IndentLine(line);

    if (!klass_->IsInterface())
    {
        line = "[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n";
        source += IndentLine(line);
        line = ToString("public static extern IntPtr csb_%s_%s_GetClassIDStatic();\n", package->GetName().CString(), klass_->GetName().CString());
        source += IndentLine(line);
        source += "\n";
    }

    Dedent();

    // managed functions

    CSFunctionWriter::SetWroteConstructor(false);

    for (unsigned i = 0; i < klass_->functions_.Size(); i++)
    {
        JSBFunction* function = klass_->functions_.At(i);

        if (function->Skip())
            continue;

        if (klass_->IsInterface() && function->IsConstructor())
            continue;

        if (function->IsDestructor())
            continue;

        if (CSTypeHelper::OmitFunction(function))
            continue;

        CSFunctionWriter fwriter(function);
        fwriter.GenerateManagedSource(source);

    }

    // There are some constructors being skipped (like HTTPRequest as it uses a vector of strings in args)
    // Make sure we have at least a IntPtr version
    if (!klass_->IsInterface() && !CSFunctionWriter::GetWroteConstructor() && klass_->GetName() != "RefCounted")
    {
        ATOMIC_LOGINFOF("WARNING: %s class didn't write a constructor, filling in generated native constructor", klass_->GetName().CString());

        line = ToString("public %s (IntPtr native) : base (native)\n", klass_->GetName().CString());
        source += IndentLine(line);
        source += IndentLine("{\n");
        source += IndentLine("}\n\n");
    }

    CSFunctionWriter::SetWroteConstructor(false);

    source += IndentLine("}\n");

    Dedent();

    sourceOut += source;
}
Ejemplo n.º 5
0
void CSModuleWriter::GenerateManagedEnumsAndConstants(String& source)
{
    Vector<SharedPtr<JSBEnum>> enums = module_->enums_.Values();

    Indent();

    for (unsigned i = 0; i < enums.Size(); i++)
    {
        JSBEnum* jenum = enums[i];

        source += "\n";
        String line = "public enum " + jenum->GetName() + "\n";
        source += IndentLine(line);
        source += IndentLine("{\n");

        HashMap<String, String>& values = jenum->GetValues();

        HashMap<String, String>::ConstIterator itr = values.Begin();

        Indent();

        while (itr != values.End())
        {
            String name = (*itr).first_;
            String value = (*itr).second_;

            if (value.Length())
            {
                line = name + " = " + value;
            }
            else
            {
                line = name;
            }

            itr++;

            if (itr != values.End())
                line += ",";

            line += "\n";

            source += IndentLine(line);

        }

        Dedent();

        source += IndentLine("}\n");

    }

    // constants

    HashMap<String, JSBModule::Constant>& constants = module_->GetConstants();

    if (constants.Size())
    {

        source += "\n";

        String line = "public static partial class Constants\n";
        source += IndentLine(line);
        source += IndentLine("{\n");

        const Vector<String>& constantsName = constants.Keys();

        Indent();

        for (unsigned i = 0; i < constantsName.Size(); i++)
        {
            const String& cname = constantsName.At(i);

            JSBModule::Constant& constant = constants[cname];

            String managedType = GetManagedPrimitiveType(constant.type);

            String value = constant.value;

            if (!value.Length())
                continue;

            //static const unsigned M_MIN_UNSIGNED = 0x00000000;
//            /static const unsigned M_MAX_UNSIGNED = 0xffffffff;

            if (cname == "M_MIN_INT")
                value = "int.MinValue";

            if (cname == "M_INFINITY")
                value = "float.MaxValue";

            if (value == "M_MAX_UNSIGNED")
                value = "0xffffffff";

            // Input stuff

            if (module_->GetName() == "Input")
            {
                if (cname.StartsWith("KEY_"))
                {
                    if (value.Length() == 1 && (IsAlpha(value[0]) || IsDigit(value[0])))
                        value = "'" + value + "'";
                }

                // https://raw.githubusercontent.com/flibitijibibo/SDL2-CS/master/src/SDL2.cs

                if (value.StartsWith("SDL_BUTTON_") || value.StartsWith("SDL_HAT_"))
                {
                    value = "(int) SDL." + value;
                }
                else if (value.StartsWith("SDLK_"))
                {
                    value = "(int) SDL.SDL_Keycode." + value;
                }
                else if (value.StartsWith("SDL_SCANCODE_"))
                {
                    value = "(int) SDL.SDL_Scancode." + value;
                }
                else if (value.StartsWith("SDL_CONTROLLER_BUTTON_"))
                {
                    value = "(int) SDL.SDL_GameControllerButton." + value;
                }
                else if (value.StartsWith("SDL_CONTROLLER_AXIS_"))
                {
                    value = "(int) SDL.SDL_GameControllerAxis." + value;
                }
            }

            String line = "public const " + managedType + " " + cname + " = " + value;

            if (managedType == "float" && !line.EndsWith("f") && IsDigit(line[line.Length()-1]))
                line += "f";

            line += ";\n";

            source += IndentLine(line);

        }

        Dedent();

        source += "\n";
        line = "}\n";
        source += IndentLine(line);

    }

    source += "\n";

    Dedent();

}
Ejemplo n.º 6
0
void CSFunctionWriter::WriteNativeFunction(String& source)
{
    JSBClass* klass = function_->GetClass();
    JSBPackage* package = klass->GetPackage();
    String fname = function_->IsConstructor() ? "Constructor" : function_->GetName();

    String returnType;
    String functionSig = CSTypeHelper::GetNativeFunctionSignature(function_, returnType);

    String line;

    line = ToString("ATOMIC_EXPORT_API %s %s\n",
                    returnType.CString(), functionSig.CString());

    source += IndentLine(line);

    source += IndentLine("{\n");

    Indent();


    source += "\n";

    bool returnValue = false;
    bool sharedPtrReturn = false;

    String returnStatement;

    if (returnType == "const char*")
    {
        returnValue = true;
        source += IndentLine("static String returnValue;\n");
        returnStatement = "returnValue = ";
    }
    else if (function_->GetReturnClass() && function_->GetReturnClass()->IsNumberArray())
    {
        returnStatement = "*returnValue = ";
    }
    else if (function_->GetReturnClass() && function_->GetReturnType()->isSharedPtr_)
    {
        returnStatement = ToString("SharedPtr<%s> returnValue = ", function_->GetReturnClass()->GetNativeName().CString());
        sharedPtrReturn = true;
    }
    else
    {
        if (returnType != "void")
        {
            returnStatement = "return ";
        }
    }

    String callSig;
    GenNativeCallParameters(callSig);
    if (!function_->isConstructor_)
    {
        if (function_->IsStatic())
        {
            line = ToString("%s%s::%s(%s);\n", returnStatement.CString(), klass->GetNativeName().CString(), function_->GetName().CString(), callSig.CString());
        }
        else
        {
            line = ToString("%sself->%s(%s);\n", returnStatement.CString(), function_->GetName().CString(), callSig.CString());
        }

    }
    else
    {
        if (klass->IsAbstract())
        {
            line = "return 0; // Abstract Class\n";
        }
        else if (klass->IsObject())
        {
            if (callSig.Length())
                line = ToString("return new %s(NETCore::GetContext(), %s);\n", klass->GetNativeName().CString(), callSig.CString());
            else
                line = ToString("return new %s(NETCore::GetContext());\n", klass->GetNativeName().CString());
        }
        else
        {
            line = ToString("return new %s(%s);\n", klass->GetNativeName().CString(), callSig.CString());
        }
    }

    source += IndentLine(line);

    if (sharedPtrReturn)
    {
        source += IndentLine("returnValue->AddRef();\n");
        source += IndentLine("return returnValue;\n");
    }
    else if (returnType == "const char*")
    {
        source += IndentLine("return returnValue.CString();\n");
    }

    Dedent();

    source += IndentLine("}\n");

    source += "\n";

}
Ejemplo n.º 7
0
void CSFunctionWriter::WriteManagedConstructor(String& source)
{
    JSBClass* klass = function_->GetClass();
    JSBPackage* package = klass->GetPackage();

    if (klass->GetName() == "RefCounted")
        return;

    // wrapping constructor

    String line;

    if (!wroteConstructor_)
    {
        line = ToString("public %s (IntPtr native) : base (native)\n", klass->GetName().CString());
        source += IndentLine(line);
        source += IndentLine("{\n");
        source += IndentLine("}\n\n");
    }

    // don't add wrapping constructor for overloads
    wroteConstructor_ = true;

    String sig;
    GenManagedFunctionParameters(sig);

    line = ToString("public %s (%s)\n", klass->GetName().CString(), sig.CString());

    source += IndentLine(line);

    source += IndentLine("{\n");

    Indent();

    WriteDefaultStructParameters(source);

    source += IndentLine("if (nativeInstance == IntPtr.Zero)\n");
    source += IndentLine("{\n");

    Indent();

    source += IndentLine(ToString("var classType = typeof(%s);\n", klass->GetName().CString()));
    source += IndentLine("var thisType = this.GetType();\n");
    source += IndentLine("var thisTypeIsNative = NativeCore.IsNativeType(thisType);\n");    
    source += IndentLine("var nativeAncsestorType = NativeCore.GetNativeAncestorType(thisType);\n");
    source += IndentLine("if ( (thisTypeIsNative && (thisType == classType)) || (!thisTypeIsNative && (nativeAncsestorType == classType)))\n");
    source += IndentLine("{\n");

    Indent();

    String callSig;
    GenPInvokeCallParameters(callSig);

    line = ToString("nativeInstance = NativeCore.RegisterNative (csb_%s_%s_Constructor_%u(%s), this);\n",
                     package->GetName().CString(), klass->GetName().CString(), function_->GetID(), callSig.CString());

    source += IndentLine(line);

    Dedent();

    source += IndentLine("}\n");

    Dedent();

    source += IndentLine("}\n");

    Dedent();

    source += IndentLine("}\n");
}
Ejemplo n.º 8
0
void CSFunctionWriter::WriteNativeFunction(String& source)
{
    JSBClass* klass = function_->GetClass();
    JSBPackage* package = klass->GetPackage();
    String fname = function_->IsConstructor() ? "Constructor" : function_->GetName();

    String returnType;
    String functionSig = CSTypeHelper::GetNativeFunctionSignature(function_, returnType);

    String line;

    line = ToString("ATOMIC_EXPORT_API %s %s\n",
                    returnType.CString(), functionSig.CString());

    source += IndentLine(line);

    source += IndentLine("{\n");

    Indent();

    source += "\n";

    // vector marshal

    bool hasVectorMarshal = false;
    const Vector<JSBFunctionType*>& fparams = function_->GetParameters();

    for (unsigned i = 0; i < fparams.Size(); i++)
    {
        JSBFunctionType* ftype = fparams[i];

        // Interface        
        JSBClass* interface = 0;
        if (ftype->type_->asClassType() && ftype->type_->asClassType()->class_->IsInterface())
        {
            // We need to downcast to the interface 
            // TODO: this assumes Object* is in hierarchy, how do we validate this?
            interface = ftype->type_->asClassType()->class_;
            line = ToString("%s = dynamic_cast<%s*>((Object*)%s);\n", ftype->name_.CString(), interface->GetNativeName().CString(), ftype->name_.CString());
            source += IndentLine(line);
        }

        // Vector
        JSBVectorType* vtype = ftype->type_->asVectorType();

        if (!vtype)
            continue;

        JSBClassType* classType = vtype->vectorType_->asClassType();

        if (!classType)
            continue;

        String className = classType->class_->GetName();

        String vectorMarshal;

        hasVectorMarshal = true;

        if (vtype->isPODVector_)
        {
            const String& pname = ftype->name_;
            source += IndentLine(ToString("PODVector<%s*> %s__vector;\n", className.CString(), pname.CString()));
            source += IndentLine(ToString("if (%s) %s->AdaptToVector<%s*>(%s__vector);\n", pname.CString(), pname.CString(), className.CString(), pname.CString()));
        }
        else
        {
            // vectorMarshal = ToString("PODVector<%s*> %s__vector", className.CString(), ftype->name_.CString());
        }

        if (vectorMarshal.Length())
        {
            source += IndentLine(vectorMarshal);
            vectorMarshal = String::EMPTY;
        }
    }


    bool returnValue = false;
    bool sharedPtrReturn = false;

    String returnStatement;

    if (returnType == "const char*")
    {
        returnValue = true;
        source += IndentLine("static String returnValue;\n");
        returnStatement = "returnValue = ";
    }
    else if (function_->GetReturnClass() && function_->GetReturnClass()->IsNumberArray())
    {
        returnStatement = "*returnValue = ";
    }
    else if (function_->GetReturnClass() && function_->GetReturnType()->isSharedPtr_)
    {
        returnStatement = ToString("SharedPtr<%s> returnValue = ", function_->GetReturnClass()->GetNativeName().CString());
        sharedPtrReturn = true;
    }
    else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
    {
        // we have an out parameter
        JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();

        if (!vtype->vectorTypeIsSharedPtr_ && !vtype->vectorTypeIsWeakPtr_)
        {
            returnStatement = ToString("%sVector<%s*> returnValue__vector = ", vtype->isPODVector_ ? "POD" : "", vtype->vectorType_->asClassType()->class_->GetName().CString());
        }
        else
        {
            returnStatement = ToString("%sVector<%s<%s>> returnValue__vector = ",  vtype->isPODVector_ ? "POD" : "", vtype->vectorTypeIsSharedPtr_ ? "SharedPtr" : "WeakPtr", vtype->vectorType_->asClassType()->class_->GetName().CString());
        }
    }
    else
    {
        if (returnType != "void" && !hasVectorMarshal)
        {
            returnStatement = "return ";
        }
        else if (returnType != "void")
        {
            returnStatement = ToString("%s returnValue = ", returnType.CString());
        }
    }

    String callSig;
    GenNativeCallParameters(callSig);
    if (!function_->isConstructor_)
    {
        if (function_->IsStatic())
        {
            line = ToString("%s%s::%s(%s);\n", returnStatement.CString(), klass->GetNativeName().CString(), function_->GetName().CString(), callSig.CString());
        }
        else
        {
            line = ToString("%sself->%s(%s);\n", returnStatement.CString(), function_->GetName().CString(), callSig.CString());
        }

    }
    else
    {
        if (klass->IsAbstract())
        {
            line = "return 0; // Abstract Class\n";
        }
        else if (klass->IsObject())
        {
            if (callSig.Length())
                line = ToString("return new %s(NETCore::GetContext(), %s);\n", klass->GetNativeName().CString(), callSig.CString());
            else
                line = ToString("return new %s(NETCore::GetContext());\n", klass->GetNativeName().CString());
        }
        else
        {
            line = ToString("return new %s(%s);\n", klass->GetNativeName().CString(), callSig.CString());
        }
    }

    source += IndentLine(line);

    // Vector marshaling

    for (unsigned i = 0; i < fparams.Size(); i++)
    {
        JSBFunctionType* ftype = fparams[i];

        JSBVectorType* vtype = ftype->type_->asVectorType();

        if (!vtype)
            continue;

        JSBClassType* classType = vtype->vectorType_->asClassType();

        if (!classType)
            continue;

        String className = classType->class_->GetName();

        String vectorMarshal;

        if (vtype->isPODVector_)
        {
            const String& pname = ftype->name_;
            source += IndentLine(ToString("if (%s) %s->AdaptFromVector<%s*>(%s__vector);\n", pname.CString(), pname.CString(), className.CString(), pname.CString()));
        }
        else
        {
            // vectorMarshal = ToString("PODVector<%s*> %s__vector", className.CString(), ftype->name_.CString());
        }

        if (vectorMarshal.Length())
        {
            source += IndentLine(vectorMarshal);
            vectorMarshal = String::EMPTY;
        }
    }


    if (sharedPtrReturn)
    {
        source += IndentLine("if (returnValue.NotNull()) returnValue->AddRef();\n");
        source += IndentLine("return returnValue;\n");
    }
    else if (returnType == "const char*")
    {
        source += IndentLine("return returnValue.CString();\n");
    }
    else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType())
    {
        // we have an out parameter
        JSBVectorType* vtype = function_->GetReturnType()->type_->asVectorType();
        source += IndentLine("if (returnValue) returnValue->AdaptFromVector(returnValue__vector);\n");

    }
    else if (returnType != "void" && hasVectorMarshal)
    {
        source += IndentLine("return returnValue;\n");
    }

    Dedent();

    source += IndentLine("}\n");

    source += "\n";

}