String CSTypeHelper::GetNativeFunctionSignature(JSBFunction* function, String& returnType) { if (function->Skip()) return String::EMPTY; if (function->IsDestructor()) return String::EMPTY; if (OmitFunction(function)) return String::EMPTY; JSBClass* klass = function->GetClass(); JSBPackage* package = klass->GetPackage(); String fname = function->IsConstructor() ? "Constructor" : function->GetName(); returnType = "void"; if (function->IsConstructor()) { returnType = "RefCounted*"; } else if (function->GetReturnType()) { if (function->IsConstructor()) { returnType = ToString("%s*", klass->GetNativeName().CString()); } else if (function->GetReturnClass()) { if (!function->GetReturnClass()->IsNumberArray()) { returnType = ToString("const %s*", function->GetReturnClass()->GetNativeName().CString()); } } else if (function->GetReturnType()->type_->asStringHashType()) { returnType = "unsigned"; } else { returnType = ToString("%s", CSTypeHelper::GetNativeTypeString(function->GetReturnType()).CString()); // ScriptVector is handled by a out parameter if (returnType.Contains("ScriptVector")) returnType = "void"; } } String sig; GenNativeFunctionParameterSignature(function, sig); String functionSig = ToString("csb_%s_%s_%s_%u(%s)", package->GetName().CString(), klass->GetName().CString(), fname.CString(), function->GetID(), sig.CString()); return functionSig; }
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"); }
void CSClassWriter::GenerateNativeSource(String& sourceOut) { String source = ""; if (klass_->IsNumberArray()) return; JSBPackage* package = klass_->GetPackage(); if (!klass_->IsInterface()) { source.AppendWithFormat("ATOMIC_EXPORT_API ClassID csb_%s_%s_GetClassIDStatic()\n{\n", package->GetName().CString(), klass_->GetName().CString()); source.AppendWithFormat(" return %s::GetClassIDStatic();\n}\n\n", klass_->GetNativeName().CString()); } WriteNativeFunctions(source); sourceOut += source; }
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; }
void CSFunctionWriter::WriteManagedPInvokeFunctionSignature(String& source) { source += "\n"; // 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); String line = "[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n"; source += IndentLine(line); JSBClass* klass = function_->GetClass(); JSBPackage* package = klass->GetPackage(); String returnType = CSTypeHelper::GetPInvokeTypeString(function_->GetReturnType()); if (returnType == "string") returnType = "IntPtr"; if (function_->IsConstructor()) returnType = "IntPtr"; Vector<JSBFunctionType*>& parameters = function_->GetParameters(); Vector<String> args; if (!function_->IsConstructor() && !function_->IsStatic()) { args.Push("IntPtr self"); } if (parameters.Size()) { for (unsigned int i = 0; i < parameters.Size(); i++) { JSBFunctionType* ptype = parameters.At(i); String name = ptype->name_; if (name == "object") name = "_object"; else if (name == "readonly") name = "readOnly"; else if (name == "params") name = "parameters"; // ignore "Context" parameters if (ptype->type_->asClassType()) { JSBClassType* classType = ptype->type_->asClassType(); JSBClass* klass = classType->class_; if (klass->GetName() == "Context") { continue; } if (klass->IsNumberArray()) { args.Push("ref " + klass->GetName() + " " + name); } else { args.Push("IntPtr " + name); } } else { args.Push(CSTypeHelper::GetPInvokeTypeString(ptype) + " " + name); } } } if (function_->GetReturnClass()) { JSBClass* retClass = function_->GetReturnClass(); if (retClass->IsNumberArray()) { args.Push("ref " + retClass->GetName() + " retValue"); } } String pstring; pstring.Join(args, ", "); String fname = function_->IsConstructor() ? "Constructor" : function_->GetName(); line = ToString("private static extern %s csb_%s_%s_%s(%s);\n", returnType.CString(), package->GetName().CString(), klass->GetName().CString(), fname.CString(), pstring.CString()); source += IndentLine(line); source += "\n"; }
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"); }
void CSFunctionWriter::WriteManagedPInvokeFunctionSignature(String& source) { JSBClass* klass = function_->GetClass(); JSBPackage* package = klass->GetPackage(); if (klass->IsInterface()) return; source += "\n"; // 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); String line = "[DllImport (Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]\n"; source += IndentLine(line); String returnType = CSTypeHelper::GetPInvokeTypeString(function_->GetReturnType()); // handled by out parameter if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType()) returnType = "void"; if (returnType == "bool") { // default boolean marshal is 4 byte windows type BOOL and not 1 byte bool // https://blogs.msdn.microsoft.com/jaredpar/2008/10/14/pinvoke-and-bool-or-should-i-say-bool/ source += IndentLine("[return: MarshalAs(UnmanagedType.I1)]\n"); } if (returnType == "string") returnType = "IntPtr"; if (function_->IsConstructor()) returnType = "IntPtr"; const Vector<JSBFunctionType*>& parameters = function_->GetParameters(); Vector<String> args; if (!function_->IsConstructor() && !function_->IsStatic()) { args.Push("IntPtr self"); } if (parameters.Size()) { for (unsigned int i = 0; i < parameters.Size(); i++) { JSBFunctionType* ptype = parameters.At(i); String name = ptype->name_; if (name == "object") name = "_object"; else if (name == "readonly") name = "readOnly"; else if (name == "params") name = "parameters"; // ignore "Context" parameters if (ptype->type_->asClassType()) { JSBClassType* classType = ptype->type_->asClassType(); JSBClass* klass = classType->class_; if (klass->GetName() == "Context") { continue; } if (klass->IsNumberArray()) { args.Push("ref " + klass->GetName() + " " + name); } else { args.Push("IntPtr " + name); } } else { args.Push(CSTypeHelper::GetPInvokeTypeString(ptype) + " " + name); } } } if (function_->GetReturnClass()) { JSBClass* retClass = function_->GetReturnClass(); if (retClass->IsNumberArray()) { args.Push("ref " + retClass->GetName() + " retValue"); } } else if (function_->GetReturnType() && function_->GetReturnType()->type_->asVectorType()) { args.Push("IntPtr returnValue"); } String pstring; pstring.Join(args, ", "); String fname = function_->IsConstructor() ? "Constructor" : function_->GetName(); line = ToString("private static extern %s csb_%s_%s_%s_%u(%s);\n", returnType.CString(), package->GetName().CString(), klass->GetName().CString(), fname.CString(), function_->GetID(), pstring.CString()); source += IndentLine(line); source += "\n"; }