|
@@ -7,13 +7,16 @@
|
|
|
|
|
|
|
|
#include <Atomic/IO/File.h>
|
|
#include <Atomic/IO/File.h>
|
|
|
#include <Atomic/IO/FileSystem.h>
|
|
#include <Atomic/IO/FileSystem.h>
|
|
|
|
|
+#include <Atomic/Core/StringUtils.h>
|
|
|
|
|
|
|
|
#include "../JSBind.h"
|
|
#include "../JSBind.h"
|
|
|
|
|
+#include "../JSBFunction.h"
|
|
|
#include "../JSBModule.h"
|
|
#include "../JSBModule.h"
|
|
|
#include "../JSBPackage.h"
|
|
#include "../JSBPackage.h"
|
|
|
#include "../JSBEnum.h"
|
|
#include "../JSBEnum.h"
|
|
|
#include "../JSBClass.h"
|
|
#include "../JSBClass.h"
|
|
|
|
|
|
|
|
|
|
+#include "CSTypeHelper.h"
|
|
|
#include "CSModuleWriter.h"
|
|
#include "CSModuleWriter.h"
|
|
|
#include "CSPackageWriter.h"
|
|
#include "CSPackageWriter.h"
|
|
|
|
|
|
|
@@ -25,9 +28,290 @@ CSPackageWriter::CSPackageWriter(JSBPackage *package) : JSBPackageWriter(package
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void CSPackageWriter::GenerateNativeFunctionThunk(String& sourceOut)
|
|
|
|
|
+{
|
|
|
|
|
+ String source, line;
|
|
|
|
|
+
|
|
|
|
|
+ source += IndentLine(ToString("\n\ntypedef struct AtomicNET%sThunk_s\n", package_->GetName().CString()));
|
|
|
|
|
+
|
|
|
|
|
+ source += IndentLine("{\n");
|
|
|
|
|
+
|
|
|
|
|
+ Indent();
|
|
|
|
|
+
|
|
|
|
|
+ PODVector<JSBClass*>& allClasses = package_->GetAllClasses();
|
|
|
|
|
+ for (unsigned i = 0; i < allClasses.Size(); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBClass* cls = allClasses[i];
|
|
|
|
|
+
|
|
|
|
|
+ PODVector<JSBFunction*>& functions = cls->GetFunctions();
|
|
|
|
|
+
|
|
|
|
|
+ for (unsigned j = 0; j < functions.Size(); j++)
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBFunction* function = functions[j];
|
|
|
|
|
+
|
|
|
|
|
+ if (!CSTypeHelper::OmitFunction(function))
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBClass* cls = function->GetClass();
|
|
|
|
|
+ JSBPackage* package = cls->GetPackage();
|
|
|
|
|
+
|
|
|
|
|
+ line = ToString("%s_%s_%s_Function ", package->GetName().CString(),
|
|
|
|
|
+ cls->GetName().CString(),
|
|
|
|
|
+ function->IsConstructor() ? "Constructor" : function->GetName().CString());
|
|
|
|
|
+
|
|
|
|
|
+ line += ToString("__%s_%s_%s;\n", package->GetName().CString(),
|
|
|
|
|
+ cls->GetName().CString(),
|
|
|
|
|
+ function->IsConstructor() ? "Constructor" : function->GetName().CString());
|
|
|
|
|
+
|
|
|
|
|
+ source += IndentLine(line);
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Dedent();
|
|
|
|
|
+
|
|
|
|
|
+ const char* packageName = package_->GetName().CString();
|
|
|
|
|
+
|
|
|
|
|
+ source += IndentLine(ToString("\n} AtomicNET%sThunk_t;\n",packageName));
|
|
|
|
|
+
|
|
|
|
|
+ source += IndentLine(ToString("extern AtomicNET%sThunk_t AtomicNET%sThunk;\n", packageName, packageName));
|
|
|
|
|
+
|
|
|
|
|
+ source += IndentLine(ToString("extern bool AtomicNET%sThunkEnabled;\n", packageName));
|
|
|
|
|
+
|
|
|
|
|
+ sourceOut += source;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void CSPackageWriter::GenNativeFunctionSignature(JSBFunction* function, String& sig)
|
|
|
|
|
+{
|
|
|
|
|
+ JSBClass* klass = function->GetClass();
|
|
|
|
|
+
|
|
|
|
|
+ Vector<JSBFunctionType*>& parameters = function->GetParameters();
|
|
|
|
|
+
|
|
|
|
|
+ Vector<String> args;
|
|
|
|
|
+
|
|
|
|
|
+ if (!function->IsConstructor())
|
|
|
|
|
+ {
|
|
|
|
|
+ args.Push(ToString("%s* self", klass->GetNativeName().CString()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (parameters.Size())
|
|
|
|
|
+ {
|
|
|
|
|
+ for (unsigned int i = 0; i < parameters.Size(); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBFunctionType* ptype = parameters.At(i);
|
|
|
|
|
+
|
|
|
|
|
+ // ignore "Context" parameters
|
|
|
|
|
+ if (ptype->type_->asClassType())
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBClassType* classType = ptype->type_->asClassType();
|
|
|
|
|
+ JSBClass* klass = classType->class_;
|
|
|
|
|
+ if (klass->GetName() == "Context")
|
|
|
|
|
+ {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ args.Push(ToString("%s* %s", klass->GetNativeName().CString(), ptype->name_.CString()));
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ args.Push(CSTypeHelper::GetNativeTypeString(ptype) + " " + ptype->name_);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (function->GetReturnClass() && function->GetReturnClass()->IsNumberArray())
|
|
|
|
|
+ {
|
|
|
|
|
+ args.Push(ToString("%s* returnValue", function->GetReturnClass()->GetNativeName().CString()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sig.Join(args, ", ");
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void CSPackageWriter::GenerateNativeFunctionTypeDefs(String& sourceOut)
|
|
|
|
|
+{
|
|
|
|
|
+ // call typedefs
|
|
|
|
|
+
|
|
|
|
|
+ Indent();
|
|
|
|
|
+
|
|
|
|
|
+ String source, line;
|
|
|
|
|
+
|
|
|
|
|
+ PODVector<JSBClass*>& allClasses = package_->GetAllClasses();
|
|
|
|
|
+ for (unsigned i = 0; i < allClasses.Size(); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBClass* cls = allClasses[i];
|
|
|
|
|
+
|
|
|
|
|
+ PODVector<JSBFunction*>& functions = cls->GetFunctions();
|
|
|
|
|
+
|
|
|
|
|
+ for (unsigned j = 0; j < functions.Size(); j++)
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBFunction* function = functions[j];
|
|
|
|
|
+ String returnType;
|
|
|
|
|
+ line = CSTypeHelper::GetNativeFunctionSignature(function, returnType, true);
|
|
|
|
|
+ if (line.Length())
|
|
|
|
|
+ {
|
|
|
|
|
+ line += ";\n";
|
|
|
|
|
+ source += IndentLine(line);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Indent();
|
|
|
|
|
+
|
|
|
|
|
+ sourceOut += source;
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void CSPackageWriter::GenerateNativeHeader()
|
|
|
|
|
+{
|
|
|
|
|
+ String source = "// This file was autogenerated by AtomicTool, changes will be lost\n\n";
|
|
|
|
|
+
|
|
|
|
|
+ source += "#pragma once\n\n";
|
|
|
|
|
+
|
|
|
|
|
+ if (package_->name_ != "Atomic")
|
|
|
|
|
+ {
|
|
|
|
|
+ source += "#include \"../../Atomic/Native/CSPackageAtomic.h\"\n";
|
|
|
|
|
+ source += "using namespace Atomic;\n";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // enum includes
|
|
|
|
|
+
|
|
|
|
|
+ PODVector<JSBHeader*> enumHeaders;
|
|
|
|
|
+ for (unsigned i = 0; i < package_->modules_.Size(); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ Vector<SharedPtr<JSBEnum>> enums = package_->modules_[i]->GetEnums();
|
|
|
|
|
+ for (unsigned j = 0; j < enums.Size(); j++)
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBHeader* header = enums[j]->GetHeader();
|
|
|
|
|
+ if (!enumHeaders.Contains(header))
|
|
|
|
|
+ enumHeaders.Push(header);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ for (unsigned i = 0; i < enumHeaders.Size(); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBHeader* header = enumHeaders[i];
|
|
|
|
|
+
|
|
|
|
|
+ String headerPath = GetPath(header->GetFilePath());
|
|
|
|
|
+
|
|
|
|
|
+ String headerfile = GetFileNameAndExtension(header->GetFilePath());
|
|
|
|
|
+
|
|
|
|
|
+ JSBind* jsbind = header->GetSubsystem<JSBind>();
|
|
|
|
|
+
|
|
|
|
|
+ headerPath.Replace(jsbind->GetSourceRootFolder() + "Source/", "");
|
|
|
|
|
+
|
|
|
|
|
+ source.AppendWithFormat("#include <%s%s>\n", headerPath.CString(), headerfile.CString());
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // forward declarations of package classes
|
|
|
|
|
+ source += ToString("namespace %s\n{\n\n", package_->GetNamespace().CString());
|
|
|
|
|
+
|
|
|
|
|
+ Indent();
|
|
|
|
|
+
|
|
|
|
|
+ PODVector<JSBClass*>& allClasses = package_->GetAllClasses();
|
|
|
|
|
+ for (unsigned i = 0; i < allClasses.Size(); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBClass* cls = allClasses[i];
|
|
|
|
|
+ source += IndentLine(ToString("class %s;\n", cls->GetNativeName().CString()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Dedent();
|
|
|
|
|
+
|
|
|
|
|
+ GenerateNativeFunctionTypeDefs(source);
|
|
|
|
|
+ GenerateNativeFunctionThunk(source);
|
|
|
|
|
+
|
|
|
|
|
+ source += "\n}\n";
|
|
|
|
|
+
|
|
|
|
|
+ JSBind* jsbind = package_->GetSubsystem<JSBind>();
|
|
|
|
|
+
|
|
|
|
|
+ String filepath = jsbind->GetDestNativeFolder() + "/CSPackage" + package_->name_ + ".h";
|
|
|
|
|
+
|
|
|
|
|
+ File file(package_->GetContext());
|
|
|
|
|
+ file.Open(filepath, FILE_WRITE);
|
|
|
|
|
+ file.Write(source.CString(), source.Length());
|
|
|
|
|
+ file.Close();
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+void CSPackageWriter::GenerateNativeThunkInit(String& sourceOut)
|
|
|
|
|
+{
|
|
|
|
|
+ const char* packageName = package_->GetName().CString();
|
|
|
|
|
+
|
|
|
|
|
+ String source, line;
|
|
|
|
|
+
|
|
|
|
|
+ for (unsigned i = 0; i < package_->modules_.Size(); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBModule* module = package_->modules_[i];
|
|
|
|
|
+ const char* moduleName = module->GetName().CString();
|
|
|
|
|
+ source.AppendWithFormat("extern \"C\" void csb_package_%s_init_%s_thunk ();\n", packageName, moduleName);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ source.AppendWithFormat("\nvoid csb_package_init_%s_thunk ()\n{\n\n", packageName);
|
|
|
|
|
+
|
|
|
|
|
+ Indent();
|
|
|
|
|
+
|
|
|
|
|
+ for (unsigned i = 0; i < package_->modules_.Size(); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ JSBModule* module = package_->modules_[i];
|
|
|
|
|
+ const char* moduleName = module->GetName().CString();
|
|
|
|
|
+ line = ToString("csb_package_%s_init_%s_thunk ();\n", packageName, moduleName);
|
|
|
|
|
+ source += IndentLine(line);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Dedent();
|
|
|
|
|
+
|
|
|
|
|
+ source.Append("\n}\n");
|
|
|
|
|
+
|
|
|
|
|
+ // Thunk Setter
|
|
|
|
|
+
|
|
|
|
|
+ String thunkType = ToString("AtomicNET%sThunk_t", packageName);
|
|
|
|
|
+ source += ToString("extern \"C\" void csb_package_set_%s_thunk (const %s *thunkIn)\n{\n", packageName, thunkType.CString());
|
|
|
|
|
+
|
|
|
|
|
+ Indent();
|
|
|
|
|
+
|
|
|
|
|
+ source += IndentLine(ToString("AtomicNET%sThunk = *thunkIn;\n", packageName));
|
|
|
|
|
+ source += IndentLine(ToString("AtomicNET%sThunkEnabled = true;\n", packageName));
|
|
|
|
|
+
|
|
|
|
|
+ Dedent();
|
|
|
|
|
+
|
|
|
|
|
+ source += ToString("\n}\n");
|
|
|
|
|
+
|
|
|
|
|
+ sourceOut += source;
|
|
|
|
|
+
|
|
|
|
|
+}
|
|
|
void CSPackageWriter::GenerateNativeSource()
|
|
void CSPackageWriter::GenerateNativeSource()
|
|
|
{
|
|
{
|
|
|
- String source = "// This file was autogenerated by JSBind, changes will be lost\n\n";
|
|
|
|
|
|
|
+ GenerateNativeHeader();
|
|
|
|
|
+
|
|
|
|
|
+ String source = "// This file was autogenerated by AtomicTool, changes will be lost\n\n";
|
|
|
|
|
+
|
|
|
|
|
+ const char* packageName = package_->name_.CString();
|
|
|
|
|
+
|
|
|
|
|
+ String packageHeader = "CSPackage" + package_->name_ + ".h";
|
|
|
|
|
+
|
|
|
|
|
+ source += ToString("#include \"%s\"\n", packageHeader.CString());
|
|
|
|
|
+
|
|
|
|
|
+ if (package_->name_ != "Atomic")
|
|
|
|
|
+ source += "using namespace Atomic;\n";
|
|
|
|
|
+
|
|
|
|
|
+ // begin namespace
|
|
|
|
|
+ source += ToString("using namespace %s;\n", packageName);
|
|
|
|
|
+
|
|
|
|
|
+ source += ToString("namespace %s\n{\n", packageName);
|
|
|
|
|
+
|
|
|
|
|
+ // thunk
|
|
|
|
|
+ source += ToString("AtomicNET%sThunk_t AtomicNET%sThunk;\n", packageName, packageName);
|
|
|
|
|
+ source += ToString("bool AtomicNET%sThunkEnabled = false;\n", packageName);
|
|
|
|
|
+
|
|
|
|
|
+ // end of namespace
|
|
|
|
|
+ source += "\n}\n";
|
|
|
|
|
+
|
|
|
|
|
+ GenerateNativeThunkInit(source);
|
|
|
|
|
|
|
|
JSBind* jsbind = package_->GetSubsystem<JSBind>();
|
|
JSBind* jsbind = package_->GetSubsystem<JSBind>();
|
|
|
|
|
|