diff --git a/source/MetadataProcessor.Console/Program.cs b/source/MetadataProcessor.Console/Program.cs
index 2983d85a..c3c636e2 100644
--- a/source/MetadataProcessor.Console/Program.cs
+++ b/source/MetadataProcessor.Console/Program.cs
@@ -127,17 +127,11 @@ public void GenerateSkeleton(
string file,
string name,
string project,
- bool withoutInteropCode)
+ bool withoutInteropCode,
+ bool isCoreLibrary)
{
try
{
- if (!withoutInteropCode)
- {
- System.Console.Error.WriteLine("Generator for Interop stubs is not supported yet.");
-
- Environment.Exit(1);
- }
-
if (Verbose) System.Console.WriteLine("Generating skeleton files...");
var skeletonGenerator = new nanoSkeletonGenerator(
@@ -145,7 +139,8 @@ public void GenerateSkeleton(
file,
name,
project,
- withoutInteropCode);
+ withoutInteropCode,
+ isCoreLibrary);
skeletonGenerator.GenerateSkeleton();
}
@@ -185,6 +180,8 @@ public static void Main(string[] args)
{
FileVersionInfo fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
+ bool isCoreLibrary = false;
+
// output header to console
System.Console.WriteLine($"nanoFramework MetadataProcessor Utility v{fileVersion.ToString()}");
System.Console.WriteLine("Copyright (c) 2019 nanoFramework project contributors");
@@ -222,8 +219,6 @@ public static void Main(string[] args)
}
else if (arg == "-compile" && i + 2 < args.Length)
{
- bool isCoreLibrary = false;
-
if (!bool.TryParse(args[i + 2], out isCoreLibrary))
{
System.Console.Error.WriteLine("Bad parameter for compile. IsCoreLib options has to be 'true' or 'false'.");
@@ -273,7 +268,8 @@ public static void Main(string[] args)
file,
name,
project,
- withoutInteropCode);
+ withoutInteropCode,
+ isCoreLibrary);
i += 4;
}
diff --git a/source/MetadataProcessor.Core/Extensions/ParameterDefintionExtensions.cs b/source/MetadataProcessor.Core/Extensions/ParameterDefintionExtensions.cs
new file mode 100644
index 00000000..c94131c2
--- /dev/null
+++ b/source/MetadataProcessor.Core/Extensions/ParameterDefintionExtensions.cs
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2019 The nanoFramework project contributors
+// See LICENSE file in the project root for full license information.
+//
+
+using Mono.Cecil;
+using System.Text;
+using System.Linq;
+
+namespace nanoFramework.Tools.MetadataProcessor.Core.Extensions
+{
+ internal static class ParameterDefintionExtensions
+ {
+ public static string TypeToString(this ParameterDefinition parameter)
+ {
+ if(parameter.ParameterType is ByReferenceType byReference)
+ {
+ // pointer to native type
+ return " *" + byReference.TypeSignatureAsString();
+ }
+ else if (parameter.ParameterType is ArrayType arrayType)
+ {
+ return "CLR_RT_TypedArray_" + arrayType.ElementType.TypeSignatureAsString();
+ }
+ else if (parameter.ParameterType.IsValueType)
+ {
+ return parameter.ParameterType.Resolve().TypeSignatureAsString();
+ }
+ else
+ {
+ return parameter.ParameterType.TypeSignatureAsString();
+ }
+ }
+ }
+}
diff --git a/source/MetadataProcessor.Core/Extensions/TypeReferenceExtensions.cs b/source/MetadataProcessor.Core/Extensions/TypeReferenceExtensions.cs
index 4a1e6fe5..40fb4001 100644
--- a/source/MetadataProcessor.Core/Extensions/TypeReferenceExtensions.cs
+++ b/source/MetadataProcessor.Core/Extensions/TypeReferenceExtensions.cs
@@ -4,6 +4,7 @@
//
using Mono.Cecil;
+using System.Text;
namespace nanoFramework.Tools.MetadataProcessor.Core.Extensions
{
@@ -13,5 +14,218 @@ public static bool IsToInclude(this TypeReference value)
{
return !nanoTablesContext.IgnoringAttributes.Contains(value.FullName);
}
+
+ public static string TypeSignatureAsString(this TypeReference type)
+ {
+ if (type.MetadataType == MetadataType.IntPtr)
+ {
+ return "I";
+ }
+
+ if (type.MetadataType == MetadataType.UIntPtr)
+ {
+ return "U";
+ }
+
+ nanoCLR_DataType dataType;
+ if (nanoSignaturesTable.PrimitiveTypes.TryGetValue(type.FullName, out dataType))
+ {
+ switch (dataType)
+ {
+ case nanoCLR_DataType.DATATYPE_VOID:
+ case nanoCLR_DataType.DATATYPE_BOOLEAN:
+ case nanoCLR_DataType.DATATYPE_CHAR:
+ case nanoCLR_DataType.DATATYPE_I1:
+ case nanoCLR_DataType.DATATYPE_U1:
+ case nanoCLR_DataType.DATATYPE_I2:
+ case nanoCLR_DataType.DATATYPE_U2:
+ case nanoCLR_DataType.DATATYPE_I4:
+ case nanoCLR_DataType.DATATYPE_U4:
+ case nanoCLR_DataType.DATATYPE_I8:
+ case nanoCLR_DataType.DATATYPE_U8:
+ case nanoCLR_DataType.DATATYPE_R4:
+ case nanoCLR_DataType.DATATYPE_BYREF:
+ case nanoCLR_DataType.DATATYPE_OBJECT:
+ return dataType.ToString().Replace("DATATYPE_", "");
+
+ case nanoCLR_DataType.DATATYPE_LAST_PRIMITIVE:
+ return "STRING";
+
+ case nanoCLR_DataType.DATATYPE_LAST_PRIMITIVE_TO_PRESERVE:
+ return "R8";
+
+ case nanoCLR_DataType.DATATYPE_LAST_PRIMITIVE_TO_MARSHAL:
+ return "TIMESPAN";
+
+ case nanoCLR_DataType.DATATYPE_REFLECTION:
+ return type.FullName.Replace(".", "");
+ }
+ }
+
+ if (type.MetadataType == MetadataType.Class)
+ {
+ StringBuilder classSig = new StringBuilder("CLASS [");
+ classSig.Append(type.MetadataToken.ToInt32().ToString("x8"));
+ classSig.Append("]");
+
+ return classSig.ToString();
+ }
+
+ if (type.MetadataType == MetadataType.ValueType)
+ {
+ StringBuilder valueTypeSig = new StringBuilder("VALUETYPE [");
+ valueTypeSig.Append(type.MetadataToken.ToInt32().ToString("x8"));
+ valueTypeSig.Append("]");
+
+ return valueTypeSig.ToString();
+ }
+
+ if (type.IsArray)
+ {
+ StringBuilder arraySig = new StringBuilder("SZARRAY ");
+ arraySig.Append(type.GetElementType().TypeSignatureAsString());
+
+ return arraySig.ToString();
+ }
+
+ return "";
+ }
+
+ public static string ToNativeTypeAsString(this TypeReference type)
+ {
+ nanoCLR_DataType dataType;
+ if (nanoSignaturesTable.PrimitiveTypes.TryGetValue(type.FullName, out dataType))
+ {
+ switch (dataType)
+ {
+ case nanoCLR_DataType.DATATYPE_VOID:
+ return "void";
+ case nanoCLR_DataType.DATATYPE_BOOLEAN:
+ return "bool";
+ case nanoCLR_DataType.DATATYPE_CHAR:
+ return "char";
+ case nanoCLR_DataType.DATATYPE_I1:
+ return "int8_t";
+ case nanoCLR_DataType.DATATYPE_U1:
+ return "uint8_t";
+ case nanoCLR_DataType.DATATYPE_I2:
+ return "int16_t";
+ case nanoCLR_DataType.DATATYPE_U2:
+ return "uint16_t";
+ case nanoCLR_DataType.DATATYPE_I4:
+ return "int32_t";
+ case nanoCLR_DataType.DATATYPE_U4:
+ return "uint32_t";
+ case nanoCLR_DataType.DATATYPE_I8:
+ return "int64_t";
+ case nanoCLR_DataType.DATATYPE_U8:
+ return "uint64_t";
+ case nanoCLR_DataType.DATATYPE_R4:
+ return "float";
+ case nanoCLR_DataType.DATATYPE_BYREF:
+ return "";
+
+ // system.String
+ case nanoCLR_DataType.DATATYPE_LAST_PRIMITIVE:
+ return "const char*";
+
+ // System.Double
+ case nanoCLR_DataType.DATATYPE_LAST_PRIMITIVE_TO_PRESERVE:
+ return "double";
+
+ default:
+ return "UNSUPPORTED";
+ }
+ }
+
+ if (type.MetadataType == MetadataType.Class)
+ {
+ return "UNSUPPORTED";
+ }
+
+ if (type.MetadataType == MetadataType.ValueType)
+ {
+ return "UNSUPPORTED";
+ }
+
+ if (type.IsArray)
+ {
+ StringBuilder arraySig = new StringBuilder("CLR_RT_TypedArray_");
+ arraySig.Append(type.GetElementType().ToCLRTypeAsString());
+
+ return arraySig.ToString();
+ }
+
+ return "";
+ }
+
+ public static string ToCLRTypeAsString(this TypeReference type)
+ {
+ nanoCLR_DataType dataType;
+ if (nanoSignaturesTable.PrimitiveTypes.TryGetValue(type.FullName, out dataType))
+ {
+ switch (dataType)
+ {
+ case nanoCLR_DataType.DATATYPE_VOID:
+ return "void";
+ case nanoCLR_DataType.DATATYPE_BOOLEAN:
+ return "bool";
+ case nanoCLR_DataType.DATATYPE_CHAR:
+ return "CHAR";
+ case nanoCLR_DataType.DATATYPE_I1:
+ return "INT8";
+ case nanoCLR_DataType.DATATYPE_U1:
+ return "UINT8";
+ case nanoCLR_DataType.DATATYPE_I2:
+ return "INT16";
+ case nanoCLR_DataType.DATATYPE_U2:
+ return "UINT16";
+ case nanoCLR_DataType.DATATYPE_I4:
+ return "INT32";
+ case nanoCLR_DataType.DATATYPE_U4:
+ return "UINT32";
+ case nanoCLR_DataType.DATATYPE_I8:
+ return "INT64";
+ case nanoCLR_DataType.DATATYPE_U8:
+ return "UINT64";
+ case nanoCLR_DataType.DATATYPE_R4:
+ return "float";
+ case nanoCLR_DataType.DATATYPE_BYREF:
+ return "NONE";
+
+ // system.String
+ case nanoCLR_DataType.DATATYPE_LAST_PRIMITIVE:
+ return "LPCSTR";
+
+ // System.Double
+ case nanoCLR_DataType.DATATYPE_LAST_PRIMITIVE_TO_PRESERVE:
+ return "double";
+
+ default:
+ return "UNSUPPORTED";
+ }
+ }
+
+ if (type.MetadataType == MetadataType.Class)
+ {
+ return "UNSUPPORTED";
+ }
+
+ if (type.MetadataType == MetadataType.ValueType)
+ {
+ return "UNSUPPORTED";
+ }
+
+ if (type.IsArray)
+ {
+ StringBuilder arraySig = new StringBuilder();
+ arraySig.Append(type.GetElementType().ToCLRTypeAsString());
+ arraySig.Append("_ARRAY");
+
+ return arraySig.ToString();
+ }
+
+ return "";
+ }
}
}
diff --git a/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj b/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj
index 76960fd9..fc052c9a 100644
--- a/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj
+++ b/source/MetadataProcessor.Core/MetadataProcessor.Core.csproj
@@ -77,6 +77,7 @@
+
diff --git a/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClass.cs b/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClass.cs
index 82c86fbb..dc408ed5 100644
--- a/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClass.cs
+++ b/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClass.cs
@@ -13,6 +13,8 @@ public class AssemblyDeclaration
public string ShortName;
public string ShortNameUpper;
+ public bool IsCoreLib = false;
+
public List Classes = new List();
}
@@ -20,10 +22,11 @@ public class Class
{
public string Name;
public string AssemblyName;
+ public string ShortNameUpper;
public List StaticFields = new List();
public List InstanceFields = new List();
- public List Methods = new List();
+ public List Methods = new List();
}
public class StaticField
@@ -40,8 +43,25 @@ public class InstanceField
public string FieldWarning;
}
- public class Method
+ public class MethodStub
+ {
+ public string Declaration;
+ public string DeclarationForUserCode;
+ public string CallFromMarshalling;
+ public string ReturnType;
+ public string MarshallingReturnType;
+ public bool HasReturnType;
+ public bool IsStatic = false;
+
+ public List ParameterDeclaration = new List();
+ }
+
+ public class ParameterDeclaration
{
+ public string Index;
+ public string Type;
+ public string Name;
+ public string MarshallingDeclaration;
public string Declaration;
}
}
diff --git a/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassStubs.cs b/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassStubs.cs
index d1c8d42d..a4e89e6b 100644
--- a/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassStubs.cs
+++ b/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyClassStubs.cs
@@ -11,6 +11,16 @@ public class AssemblyClassStubs
{
public string HeaderFileName;
- public List Functions = new List();
+ public string ClassHeaderFileName;
+
+ public string ClassName;
+
+ public string ShortNameUpper;
+
+ public string RootNamespace;
+
+ public string ProjectName;
+
+ public List Functions = new List();
}
}
diff --git a/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyLookupTable.cs b/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyLookupTable.cs
index 79dbcb9c..5dae9118 100644
--- a/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyLookupTable.cs
+++ b/source/MetadataProcessor.Core/SkeletonGenerator/AssemblyLookupTable.cs
@@ -10,6 +10,8 @@ namespace nanoFramework.Tools.MetadataProcessor.Core
{
public class AssemblyLookupTable
{
+ public bool IsCoreLib;
+
public string Name;
public string AssemblyName;
public string HeaderFileName;
@@ -17,6 +19,6 @@ public class AssemblyLookupTable
public Version NativeVersion;
- public List LookupTable = new List();
+ public List LookupTable = new List();
}
}
diff --git a/source/MetadataProcessor.Core/SkeletonGenerator/SkeletonTemplates.cs b/source/MetadataProcessor.Core/SkeletonGenerator/SkeletonTemplates.cs
index d78dc667..8a6172af 100644
--- a/source/MetadataProcessor.Core/SkeletonGenerator/SkeletonTemplates.cs
+++ b/source/MetadataProcessor.Core/SkeletonGenerator/SkeletonTemplates.cs
@@ -8,7 +8,9 @@ namespace nanoFramework.Tools.MetadataProcessor
internal partial class SkeletonTemplates
{
internal const string AssemblyHeaderTemplate =
-@"//-----------------------------------------------------------------------------{{#newline}}
+@"
+{{#if IsCoreLib}}
+//-----------------------------------------------------------------------------{{#newline}}
//{{#newline}}
// ** WARNING! ** {{#newline}}
// This file was generated automatically by a tool.{{#newline}}
@@ -19,6 +21,15 @@ internal partial class SkeletonTemplates
// re-run.{{#newline}}
//{{#newline}}
//-----------------------------------------------------------------------------{{#newline}}
+{{#else}}
+//-----------------------------------------------------------------------------{{#newline}}
+//{{#newline}}
+// ** DO NOT EDIT THIS FILE! **{{#newline}}
+// This file was generated by a tool{{#newline}}
+// re-running the tool will overwrite this file.{{#newline}}
+//{{#newline}}
+//-----------------------------------------------------------------------------{{#newline}}
+{{/if}}
{{#newline}}
#ifndef _{{ShortNameUpper}}_H_{{#newline}}
@@ -27,7 +38,10 @@ internal partial class SkeletonTemplates
#include {{#newline}}
#include {{#newline}}
+{{#if IsCoreLib}}
#include {{#newline}}
+{{#else}}
+{{/if}}
{{#newline}}
{{#each Classes}}
@@ -61,7 +75,20 @@ struct Library_{{AssemblyName}}_{{Name}}{{#newline}}
";
internal const string AssemblyLookupTemplate =
-@"#include ""{{HeaderFileName}}.h""{{#newline}}
+@"
+{{#if IsCoreLib}}
+{{#else}}
+//-----------------------------------------------------------------------------{{#newline}}
+//{{#newline}}
+// ** DO NOT EDIT THIS FILE! **{{#newline}}
+// This file was generated by a tool{{#newline}}
+// re-running the tool will overwrite this file.{{#newline}}
+//{{#newline}}
+//-----------------------------------------------------------------------------{{#newline}}
+{{#newline}}
+{{/if}}
+
+#include ""{{HeaderFileName}}.h""{{#newline}}
{{#newline}}
static const CLR_RT_MethodHandler method_lookup[] ={{#newline}}
@@ -77,14 +104,11 @@ struct Library_{{AssemblyName}}_{{Name}}{{#newline}}
""{{Name}}"",{{#newline}}
{{NativeCRC32}},{{#newline}}
method_lookup,{{#newline}}
- ////////////////////////////////////////////////////////////////////////////////////{{#newline}}
- // check if the version bellow matches the one in AssemblyNativeVersion attribute //{{#newline}}
- ////////////////////////////////////////////////////////////////////////////////////{{#newline}}
{ {{NativeVersion.Major}}, {{NativeVersion.Minor}}, {{NativeVersion.Build}}, {{NativeVersion.Revision}} }{{#newline}}
};{{#newline}}
";
- internal const string ClassStubTemplate =
+ internal const string ClassWithoutInteropStubTemplate =
@"//-----------------------------------------------------------------------------
//
// ** WARNING! **
@@ -108,6 +132,108 @@ struct Library_{{AssemblyName}}_{{Name}}{{#newline}}
NANOCLR_NOCLEANUP();
}
+{{/each}}";
+
+ internal const string ClassStubTemplate =
+@"//-----------------------------------------------------------------------------
+//
+// ** WARNING! **
+// This file was generated automatically by a tool.
+// Re-running the tool will overwrite this file.
+// You should copy this file to a custom location
+// before adding any customization in the copy to
+// prevent loss of your changes when the tool is
+// re-run.
+//
+//-----------------------------------------------------------------------------
+
+#include ""{{HeaderFileName}}.h""
+#include ""{{HeaderFileName}}_{{ClassHeaderFileName}}.h""
+
+using namespace {{RootNamespace}}::{{ProjectName}};
+
+{{#each Functions}}
+{{ReturnType}} {{ClassName}}::{{DeclarationForUserCode}}
+{
+{{#each ParameterDeclaration}}
+ (void){{Name}};{{/each}}
+ (void)hr;
+{{#if HasReturnType}} {{ReturnType}} retValue = 0;{{/if}}
+
+ ////////////////////////////////
+ // implementation starts here //
+
+
+ // implementation ends here //
+ ////////////////////////////////
+
+{{#if HasReturnType}} return retValue;{{/if}}
+}
+{{/each}}";
+
+ internal const string ClassHeaderTemplate =
+@"//-----------------------------------------------------------------------------
+//
+// ** WARNING! **
+// This file was generated automatically by a tool.
+// Re-running the tool will overwrite this file.
+// You should copy this file to a custom location
+// before adding any customization in the copy to
+// prevent loss of your changes when the tool is
+// re-run.
+//
+//-----------------------------------------------------------------------------
+
+#ifndef _{{ShortNameUpper}}_H_
+#define _{{ShortNameUpper}}_H_
+
+namespace {{RootNamespace}}
+{
+ namespace {{ProjectName}}
+ {
+ struct {{ClassName}}
+ {
+ // Helper Functions to access fields of managed object
+ // Declaration of stubs. These functions are implemented by Interop code developers
+{{#each Functions}}
+ {{#if IsStatic}}static {{/if}}{{ReturnType}} {{DeclarationForUserCode}};
+{{/each}}
+ };
+ }
+}
+
+#endif //_{{ShortNameUpper}}_H_
+";
+
+ internal const string ClassMarshallingCodeTemplate =
+@"//-----------------------------------------------------------------------------
+//
+// ** DO NOT EDIT THIS FILE! **
+// This file was generated by a tool
+// re-running the tool will overwrite this file.
+//
+//-----------------------------------------------------------------------------
+
+#include ""{{HeaderFileName}}.h""
+#include ""{{HeaderFileName}}_{{ClassHeaderFileName}}.h""
+
+using namespace {{RootNamespace}}::{{ProjectName}};
+
+{{#each Functions}}
+HRESULT {{Declaration}}( CLR_RT_StackFrame& stack )
+{
+ NANOCLR_HEADER(); hr = S_OK;
+ {
+{{#each ParameterDeclaration}}
+ {{Declaration}}
+ NANOCLR_CHECK_HRESULT( {{MarshallingDeclaration}} );
+{{/each}}
+ {{#if HasReturnType}}{{ReturnType}} retValue = {{/if}}{{ClassName}}::{{CallFromMarshalling}};
+ NANOCLR_CHECK_HRESULT( hr );
+{{#if HasReturnType}} SetResult_{{MarshallingReturnType}}( stack, retValue );{{/if}}
+ }
+ NANOCLR_NOCLEANUP();
+}
{{/each}}";
}
}
diff --git a/source/MetadataProcessor.Core/nanoDumperGenerator.cs b/source/MetadataProcessor.Core/nanoDumperGenerator.cs
index 16f53793..15f182f4 100644
--- a/source/MetadataProcessor.Core/nanoDumperGenerator.cs
+++ b/source/MetadataProcessor.Core/nanoDumperGenerator.cs
@@ -153,7 +153,7 @@ private void DumpTypeDefinitions(DumpAllTable dumpTable)
Name = f.Name,
Flags = att.ToString("x8"),
Attributes = att.ToString("x8"),
- Signature = PrintSignatureForType(f.FieldType)
+ Signature = f.FieldType.TypeSignatureAsString()
};
typeDef.FieldDefinitions.Add(fieldDef);
@@ -310,87 +310,15 @@ private void DumpAssemblyReferences(DumpAllTable dumpTable)
}
}
- private string PrintSignatureForType(TypeReference type)
- {
- if(type.MetadataType == MetadataType.IntPtr)
- {
- return "I";
- }
-
- if (type.MetadataType == MetadataType.UIntPtr)
- {
- return "U";
- }
-
- nanoCLR_DataType dataType;
- if (nanoSignaturesTable.PrimitiveTypes.TryGetValue(type.FullName, out dataType))
- {
- switch(dataType)
- {
- case nanoCLR_DataType.DATATYPE_VOID:
- case nanoCLR_DataType.DATATYPE_BOOLEAN:
- case nanoCLR_DataType.DATATYPE_CHAR:
- case nanoCLR_DataType.DATATYPE_I1:
- case nanoCLR_DataType.DATATYPE_U1:
- case nanoCLR_DataType.DATATYPE_I2:
- case nanoCLR_DataType.DATATYPE_U2:
- case nanoCLR_DataType.DATATYPE_I4:
- case nanoCLR_DataType.DATATYPE_U4:
- case nanoCLR_DataType.DATATYPE_I8:
- case nanoCLR_DataType.DATATYPE_U8:
- case nanoCLR_DataType.DATATYPE_R4:
- case nanoCLR_DataType.DATATYPE_R8:
- case nanoCLR_DataType.DATATYPE_BYREF:
- case nanoCLR_DataType.DATATYPE_OBJECT:
- return dataType.ToString().Replace("DATATYPE_", "");
-
- case nanoCLR_DataType.DATATYPE_LAST_PRIMITIVE:
- return "STRING";
-
- case nanoCLR_DataType.DATATYPE_REFLECTION:
- return type.FullName.Replace(".", "");
- }
- }
-
- if (type.MetadataType == MetadataType.Class)
- {
- StringBuilder classSig = new StringBuilder("CLASS [");
- classSig.Append(type.MetadataToken.ToInt32().ToString("x8"));
- classSig.Append("]");
-
- return classSig.ToString();
- }
-
- if (type.MetadataType == MetadataType.ValueType)
- {
- StringBuilder valueTypeSig = new StringBuilder("VALUETYPE [");
- valueTypeSig.Append(type.MetadataToken.ToInt32().ToString("x8"));
- valueTypeSig.Append("]");
-
- return valueTypeSig.ToString();
- }
-
- if (type.IsArray)
- {
- StringBuilder arraySig = new StringBuilder("SZARRAY ");
- arraySig.Append(PrintSignatureForType(type.GetElementType()));
-
- return arraySig.ToString();
- }
-
-
- return "";
- }
-
private string PrintSignatureForMethod(MethodReference method)
{
- var sig = new StringBuilder(PrintSignatureForType(method.ReturnType));
+ var sig = new StringBuilder(method.ReturnType.TypeSignatureAsString());
sig.Append("( ");
foreach(var p in method.Parameters)
{
- sig.Append(PrintSignatureForType(p.ParameterType));
+ sig.Append(p.ParameterType.TypeSignatureAsString());
sig.Append(", ");
}
@@ -417,7 +345,7 @@ private string PrintSignatureForLocalVar(Collection variable
foreach (var l in variables)
{
- sig.Append(PrintSignatureForType(l.VariableType));
+ sig.Append(l.VariableType.TypeSignatureAsString());
sig.Append(", ");
}
diff --git a/source/MetadataProcessor.Core/nanoSkeletonGenerator.cs b/source/MetadataProcessor.Core/nanoSkeletonGenerator.cs
index 94b8325b..ef02542c 100644
--- a/source/MetadataProcessor.Core/nanoSkeletonGenerator.cs
+++ b/source/MetadataProcessor.Core/nanoSkeletonGenerator.cs
@@ -9,6 +9,7 @@
using System;
using System.IO;
using System.Linq;
+using System.Text;
namespace nanoFramework.Tools.MetadataProcessor.Core
{
@@ -22,7 +23,7 @@ public sealed class nanoSkeletonGenerator
private readonly string _name;
private readonly string _project;
private readonly bool _withoutInteropCode;
-
+ private readonly bool _isCoreLib;
private string _assemblyName;
public nanoSkeletonGenerator(
@@ -30,13 +31,15 @@ public nanoSkeletonGenerator(
string path,
string name,
string project,
- bool withoutInteropCode)
+ bool withoutInteropCode,
+ bool isCoreLib)
{
_tablesContext = tablesContext;
_path = path;
_name = name;
_project = project;
_withoutInteropCode = withoutInteropCode;
+ _isCoreLib = isCoreLib;
}
public void GenerateSkeleton()
@@ -50,7 +53,7 @@ public void GenerateSkeleton()
// generate .cpp with the lookup definition
GenerateAssemblyLookup();
- // generate _.cpp files with the type definition and stubs.
+ // generate stub files for classes, headers and marshalling code, if required
GenerateStubs();
}
@@ -63,10 +66,30 @@ private void GenerateStubs()
{
var className = NativeMethodsCrc.GetClassName(c);
- var classStubs = new AssemblyClassStubs()
+ var classStubs = new AssemblyClassStubs();
+
+ if (!_withoutInteropCode)
{
- HeaderFileName = _project
- };
+ // Interop code needs to use the root namespace
+
+ classStubs.HeaderFileName = $"{_assemblyName}_{_project}";
+ classStubs.ClassHeaderFileName = className;
+ classStubs.ClassName = c.Name;
+ classStubs.ShortNameUpper = $"{_assemblyName}_{_project}_{className}".ToUpper();
+ classStubs.RootNamespace = _assemblyName;
+ classStubs.ProjectName = _project;
+ }
+ else
+ {
+ // projects with Interop can use a simplified naming
+
+ classStubs.HeaderFileName = _project;
+ classStubs.ClassHeaderFileName = className;
+ classStubs.ClassName = c.Name;
+ classStubs.ShortNameUpper = $"{_assemblyName}_{_project}_{className}".ToUpper();
+ classStubs.RootNamespace = _assemblyName;
+ classStubs.ProjectName = _project;
+ }
foreach (var m in nanoTablesContext.GetOrderedMethods(c.Methods))
{
@@ -76,26 +99,159 @@ private void GenerateStubs()
if (rva == 0xFFFF &&
!m.IsAbstract)
{
- classStubs.Functions.Add(new Method()
+ var newMethod = new MethodStub()
{
Declaration = $"Library_{_project}_{className}::{NativeMethodsCrc.GetMethodName(m)}"
- });
+ };
+
+ if(!_withoutInteropCode)
+ {
+ // process with Interop code
+
+ newMethod.IsStatic = m.IsStatic;
+ newMethod.HasReturnType = (
+ m.MethodReturnType != null &&
+ m.MethodReturnType.ReturnType.FullName != "System.Void");
+
+ StringBuilder declaration = new StringBuilder();
+
+ newMethod.ReturnType = m.MethodReturnType.ReturnType.ToNativeTypeAsString();
+
+ newMethod.MarshallingReturnType = newMethod.ReturnType;
+
+ declaration.Append($"{m.Name}");
+ declaration.Append("( ");
+
+ StringBuilder marshallingCall = new StringBuilder($"{m.Name}");
+ marshallingCall.Append("( ");
+
+ // loop through the parameters
+ if (m.HasParameters)
+ {
+ int parameterIndex = 0;
+
+ foreach (var item in m.Parameters)
+ {
+ // get the parameter type
+ var parameterType = item.ParameterType.ToNativeTypeAsString();
+
+ // compose the function declaration
+ declaration.Append($"{parameterType} param{parameterIndex.ToString()}, ");
+
+ // compose the function call
+ marshallingCall.Append($"param{parameterIndex.ToString()}, ");
+
+ // compose the variable block
+ var parameterDeclaration = new ParameterDeclaration()
+ {
+ Index = parameterIndex.ToString(),
+ Name = $"param{parameterIndex.ToString()}",
+ };
+
+ if(item.ParameterType.IsByReference)
+ {
+ // declaration like
+ // INT8 param1;
+ // UINT8 heapblock1[CLR_RT_HEAP_BLOCK_SIZE];
+
+ parameterDeclaration.Type = parameterType;
+
+ parameterDeclaration.Declaration =
+ $"{parameterType} {parameterDeclaration.Name};" + Environment.NewLine +
+ $" UINT8 heapblock{parameterIndex.ToString()}[CLR_RT_HEAP_BLOCK_SIZE];";
+
+ parameterDeclaration.MarshallingDeclaration = $"Interop_Marshal_{parameterType}_ByRef( stack, heapblock{(parameterIndex + (m.IsStatic ? 0 : 1)).ToString()}, {parameterDeclaration.Name} )";
+
+ }
+ else if (item.ParameterType.IsArray)
+ {
+ // declaration like
+ // CLR_RT_TypedArray_UINT8 param0;
+
+ parameterDeclaration.Type = parameterType;
+ parameterDeclaration.Declaration = $"{parameterType} {parameterDeclaration.Name};";
+ parameterDeclaration.MarshallingDeclaration = $"Interop_Marshal_{item.ParameterType.GetElementType().ToCLRTypeAsString()}_ARRAY( stack, {(parameterIndex + (m.IsStatic ? 0 : 1)).ToString()}, {parameterDeclaration.Name} )";
+ }
+ else
+ {
+ // declaration like
+ // INT8 param1;
+
+ parameterDeclaration.Type = parameterType;
+ parameterDeclaration.Declaration = $"{parameterType} {parameterDeclaration.Name};";
+ parameterDeclaration.MarshallingDeclaration = $"Interop_Marshal_{parameterType}( stack, {(parameterIndex + (m.IsStatic ? 0 : 1)).ToString()}, {parameterDeclaration.Name} )";
+ }
+
+ newMethod.ParameterDeclaration.Add(parameterDeclaration);
+ }
+
+ declaration.Append("HRESULT &hr )");
+ marshallingCall.Append("hr )");
+ }
+ else
+ {
+ declaration.Append(" HRESULT &hr )");
+ marshallingCall.Append(" hr )");
+ }
+
+ newMethod.DeclarationForUserCode = declaration.ToString();
+ newMethod.CallFromMarshalling = marshallingCall.ToString();
+ }
+
+ classStubs.Functions.Add(newMethod);
}
}
// anything to add to the header?
if (classStubs.Functions.Count > 0)
{
- FormatCompiler compiler = new FormatCompiler
+ if (_withoutInteropCode)
{
- RemoveNewLines = false
- };
- Generator generator = compiler.Compile(SkeletonTemplates.ClassStubTemplate);
+ FormatCompiler compiler = new FormatCompiler
+ {
+ RemoveNewLines = false
+ };
+ Generator generator = compiler.Compile(SkeletonTemplates.ClassWithoutInteropStubTemplate);
- using (var headerFile = File.CreateText(Path.Combine(_path, $"{_project}_{className}.cpp")))
+ using (var headerFile = File.CreateText(Path.Combine(_path, $"{_project}_{className}.cpp")))
+ {
+ var output = generator.Render(classStubs);
+ headerFile.Write(output);
+ }
+ }
+ else
{
- var output = generator.Render(classStubs);
- headerFile.Write(output);
+ FormatCompiler compiler = new FormatCompiler
+ {
+ RemoveNewLines = false
+ };
+
+ // user code stub
+ Generator generator = compiler.Compile(SkeletonTemplates.ClassStubTemplate);
+
+ using (var headerFile = File.CreateText(Path.Combine(_path, $"{_assemblyName}_{_project}_{className}.cpp")))
+ {
+ var output = generator.Render(classStubs);
+ headerFile.Write(output);
+ }
+
+ // marshal code
+ generator = compiler.Compile(SkeletonTemplates.ClassMarshallingCodeTemplate);
+
+ using (var headerFile = File.CreateText(Path.Combine(_path, $"{_assemblyName}_{_project}_{className}_mrsh.cpp")))
+ {
+ var output = generator.Render(classStubs);
+ headerFile.Write(output);
+ }
+
+ // class header
+ generator = compiler.Compile(SkeletonTemplates.ClassHeaderTemplate);
+
+ using (var headerFile = File.CreateText(Path.Combine(_path, $"{_assemblyName}_{_project}_{className}.h")))
+ {
+ var output = generator.Render(classStubs);
+ headerFile.Write(output);
+ }
}
}
}
@@ -110,6 +266,7 @@ private void GenerateAssemblyLookup()
var assemblyLookup = new AssemblyLookupTable()
{
+ IsCoreLib = _isCoreLib,
Name = _name,
AssemblyName = _assemblyName,
HeaderFileName = _project,
@@ -139,7 +296,7 @@ private void GenerateAssemblyLookup()
if ((rva == 0xFFFF &&
!m.IsAbstract))
{
- assemblyLookup.LookupTable.Add(new Method()
+ assemblyLookup.LookupTable.Add(new MethodStub()
{
Declaration = $"Library_{_project}_{className}::{NativeMethodsCrc.GetMethodName(m)}"
});
@@ -152,7 +309,7 @@ private void GenerateAssemblyLookup()
if (!c.IsClassToExclude())
{
- assemblyLookup.LookupTable.Add(new Method()
+ assemblyLookup.LookupTable.Add(new MethodStub()
{
Declaration = "NULL"
//Declaration = $"**Library_{_project}_{NativeMethodsCrc.GetClassName(c)}::{NativeMethodsCrc.GetMethodName(m)}"
@@ -172,7 +329,7 @@ private void GenerateAssemblyLookup()
{
foreach (var m in nanoTablesContext.GetOrderedMethods(c.Methods))
{
- assemblyLookup.LookupTable.Add(new Method()
+ assemblyLookup.LookupTable.Add(new MethodStub()
{
Declaration = "NULL"
//Declaration = $"**Library_{_project}_{NativeMethodsCrc.GetClassName(c)}::{NativeMethodsCrc.GetMethodName(m)}"
@@ -185,8 +342,20 @@ private void GenerateAssemblyLookup()
FormatCompiler compiler = new FormatCompiler();
Generator generator = compiler.Compile(SkeletonTemplates.AssemblyLookupTemplate);
+ string filePath;
+
+ if (!_withoutInteropCode)
+ {
+ // Interop code needs to use the root namespace
+ filePath = Path.Combine(_path, $"{_assemblyName}_{_project}.cpp");
+ }
+ else
+ {
+ // projects with Interop can use a simplified naming
+ filePath = Path.Combine(_path, $"{_project}.cpp");
+ }
- using (var headerFile = File.CreateText(Path.Combine(_path, $"{_project}.cpp")))
+ using (var headerFile = File.CreateText(filePath))
{
var output = generator.Render(assemblyLookup);
headerFile.Write(output);
@@ -201,7 +370,8 @@ private void GenerateAssemblyHeader()
{
Name = _name.Replace('.', '_'),
ShortName = _project,
- ShortNameUpper = _project.ToUpperInvariant()
+ ShortNameUpper = _project.ToUpperInvariant(),
+ IsCoreLib = _isCoreLib
};
foreach (var c in _tablesContext.TypeDefinitionTable.Items)
@@ -215,6 +385,15 @@ private void GenerateAssemblyHeader()
Name = NativeMethodsCrc.GetClassName(c)
};
+ // If class name starts from ,
+ // then we need to exclude this class as actually this is static data object
+ // described in metadata.
+ if (classData.Name.StartsWith(""))
+ {
+ // Go to the next class. This metadata describes global variable, not a type
+ continue;
+ }
+
// static fields
int fieldCount = 0;
var staticFields = c.Fields.Where(f => f.IsStatic && !f.IsLiteral);
@@ -273,7 +452,7 @@ private void GenerateAssemblyHeader()
if( rva == 0xFFFF &&
!m.IsAbstract)
{
- classData.Methods.Add(new Method()
+ classData.Methods.Add(new MethodStub()
{
Declaration = NativeMethodsCrc.GetMethodName(m)
});
@@ -296,8 +475,20 @@ private void GenerateAssemblyHeader()
Generator generator = compiler.Compile(SkeletonTemplates.AssemblyHeaderTemplate);
Directory.CreateDirectory(_path);
+ string filePath;
+
+ if (!_withoutInteropCode)
+ {
+ // Interop code needs to use the root namespace
+ filePath = Path.Combine(_path, $"{_assemblyName}_{_project}.h");
+ }
+ else
+ {
+ // projects with Interop can use a simplified naming
+ filePath = Path.Combine(_path, $"{_project}.h");
+ }
- using (var headerFile = File.CreateText(Path.Combine(_path, $"{_project}.h")))
+ using (var headerFile = File.CreateText(filePath))
{
var output = generator.Render(assemblyData);
headerFile.Write(output);
diff --git a/source/version.json b/source/version.json
index 49193d14..f80dc452 100644
--- a/source/version.json
+++ b/source/version.json
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/AArnott/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
- "version": "2.19.0",
+ "version": "2.20.0",
"release": {
"branchName" : "release-v{version}",
"versionIncrement" : "minor",