Skip to content

Commit 4da4bac

Browse files
Stub generation fixes (#154)
1 parent 3f87195 commit 4da4bac

File tree

5 files changed

+202
-26
lines changed

5 files changed

+202
-26
lines changed

MetadataProcessor.Shared/SkeletonGenerator/SkeletonTemplates.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ struct {{ClassName}}
216216
// Helper Functions to access fields of managed object
217217
// Declaration of stubs. These functions are implemented by Interop code developers
218218
{{#each Functions}}
219-
{{#if IsStatic}}static {{/if}}{{ReturnType}} {{DeclarationForUserCode}};
219+
static {{ReturnType}} {{DeclarationForUserCode}};
220220
{{/each}}
221221
};
222222
}

MetadataProcessor.Shared/nanoSkeletonGenerator.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -154,12 +154,14 @@ private void GenerateStubs()
154154
{
155155
// get the parameter type
156156
string parameterType = string.Empty;
157+
string parameterTypeWORef = string.Empty;
157158
string parameterTypeClr = string.Empty;
158159

159160
if (item.ParameterType.IsByReference)
160161
{
161162
// for ref types need an extra step to get the element type
162163
parameterType = item.ParameterType.GetElementType().ToNativeTypeAsString() + "&";
164+
parameterTypeWORef = item.ParameterType.GetElementType().ToNativeTypeAsString();
163165
parameterTypeClr = item.ParameterType.GetElementType().ToCLRTypeAsString();
164166
}
165167
else
@@ -169,16 +171,24 @@ private void GenerateStubs()
169171
}
170172

171173
// compose the function declaration
172-
declaration.Append($"{parameterType} param{parameterIndex.ToString()}, ");
174+
declaration.Append($"{parameterType} param{parameterIndex}, ");
173175

174176
// compose the function call
175-
marshallingCall.Append($"param{parameterIndex.ToString()}, ");
177+
if (item.ParameterType.IsByReference)
178+
{
179+
marshallingCall.Append($"*param{parameterIndex}, ");
180+
}
181+
else
182+
{
183+
marshallingCall.Append($"param{parameterIndex}, ");
184+
}
185+
176186

177187
// compose the variable block
178188
var parameterDeclaration = new ParameterDeclaration()
179189
{
180190
Index = parameterIndex.ToString(),
181-
Name = $"param{parameterIndex.ToString()}",
191+
Name = $"param{parameterIndex}",
182192
};
183193

184194
if(item.ParameterType.IsByReference)
@@ -190,10 +200,10 @@ private void GenerateStubs()
190200
parameterDeclaration.Type = parameterType;
191201

192202
parameterDeclaration.Declaration =
193-
$"{parameterType} {parameterDeclaration.Name};" + Environment.NewLine +
194-
$" UINT8 heapblock{parameterIndex.ToString()}[CLR_RT_HEAP_BLOCK_SIZE];";
203+
$"{parameterTypeWORef} *{parameterDeclaration.Name};" + Environment.NewLine +
204+
$" uint8_t heapblock{parameterIndex}[CLR_RT_HEAP_BLOCK_SIZE];";
195205

196-
parameterDeclaration.MarshallingDeclaration = $"Interop_Marshal_{parameterTypeClr}_ByRef( stack, heapblock{(parameterIndex + (m.IsStatic ? 0 : 1)).ToString()}, {parameterDeclaration.Name} )";
206+
parameterDeclaration.MarshallingDeclaration = $"Interop_Marshal_{parameterTypeClr}_ByRef( stack, heapblock{parameterIndex}, {(parameterIndex + (m.IsStatic ? 0 : 1))}, {parameterDeclaration.Name} )";
197207

198208
}
199209
else if (item.ParameterType.IsArray)
@@ -203,7 +213,7 @@ private void GenerateStubs()
203213

204214
parameterDeclaration.Type = parameterType;
205215
parameterDeclaration.Declaration = $"{parameterType} {parameterDeclaration.Name};";
206-
parameterDeclaration.MarshallingDeclaration = $"Interop_Marshal_{parameterTypeClr}( stack, {(parameterIndex + (m.IsStatic ? 0 : 1)).ToString()}, {parameterDeclaration.Name} )";
216+
parameterDeclaration.MarshallingDeclaration = $"Interop_Marshal_{parameterTypeClr}( stack, {(parameterIndex + (m.IsStatic ? 0 : 1))}, {parameterDeclaration.Name} )";
207217
}
208218
else
209219
{
@@ -212,8 +222,8 @@ private void GenerateStubs()
212222

213223
parameterDeclaration.Type = parameterType;
214224
parameterDeclaration.Declaration = $"{parameterType} {parameterDeclaration.Name};";
215-
parameterDeclaration.MarshallingDeclaration = $"Interop_Marshal_{parameterTypeClr}( stack, {(parameterIndex + (m.IsStatic ? 0 : 1)).ToString()}, {parameterDeclaration.Name} )";
216-
}
225+
parameterDeclaration.MarshallingDeclaration = $"Interop_Marshal_{parameterTypeClr}( stack, {(parameterIndex + (m.IsStatic ? 0 : 1))}, {parameterDeclaration.Name} )";
226+
}
217227
newMethod.ParameterDeclaration.Add(parameterDeclaration);
218228
parameterIndex++;
219229
}

MetadataProcessor.Tests/Core/StubsGenerationTests.cs

Lines changed: 176 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ namespace nanoFramework.Tools.MetadataProcessor.Tests.Core
1515
[TestClass]
1616
public class StubsGenerationTests
1717
{
18-
private const string NativeMethodGenerationDeclaration = @"void NativeMethodGeneration::NativeMethodWithReferenceParameters( uint8_t& param0, uint16_t& param1, HRESULT &hr )
18+
private const string NativeMethodGenerationDeclaration =
19+
@"void NativeMethodGeneration::NativeMethodWithReferenceParameters( uint8_t& param0, uint16_t& param1, HRESULT &hr )
1920
{
2021
2122
(void)param0;
@@ -33,8 +34,171 @@ public class StubsGenerationTests
3334
3435
}";
3536

37+
private const string NativeMarshallingMethodGenerationDeclaration =
38+
@"HRESULT Library_StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration::NativeMethodWithReferenceParameters___VOID__BYREF_U1__BYREF_U2( CLR_RT_StackFrame& stack )
39+
{
40+
NANOCLR_HEADER(); hr = S_OK;
41+
{
42+
43+
uint8_t *param0;
44+
uint8_t heapblock0[CLR_RT_HEAP_BLOCK_SIZE];
45+
NANOCLR_CHECK_HRESULT( Interop_Marshal_UINT8_ByRef( stack, heapblock0, 1, param0 ) );
46+
47+
uint16_t *param1;
48+
uint8_t heapblock1[CLR_RT_HEAP_BLOCK_SIZE];
49+
NANOCLR_CHECK_HRESULT( Interop_Marshal_UINT16_ByRef( stack, heapblock1, 2, param1 ) );
50+
51+
NativeMethodGeneration::NativeMethodWithReferenceParameters( *param0, *param1, hr );
52+
NANOCLR_CHECK_HRESULT( hr );
53+
54+
}
55+
NANOCLR_NOCLEANUP();
56+
}";
57+
58+
private const string NativeHeaderMethodGenerationDeclaration =
59+
"static void NativeMethodWithReferenceParameters( uint8_t& param0, uint16_t& param1, HRESULT &hr );";
60+
61+
private string stubPath;
62+
3663
[TestMethod]
3764
public void GeneratingStubsFromNFAppTest()
65+
{
66+
// read generated stub file and look for the function declaration
67+
var generatedFile =
68+
File.ReadAllText(
69+
$"{stubPath}\\StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration.cpp");
70+
71+
Assert.IsTrue(generatedFile.Contains(NativeMethodGenerationDeclaration));
72+
}
73+
74+
[TestMethod]
75+
public void GeneratingMarshallingStubsFromNFAppTest()
76+
{
77+
var generatedFile =
78+
File.ReadAllText(
79+
$"{stubPath}\\StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration_mshl.cpp");
80+
81+
Assert.IsTrue(generatedFile.Contains(NativeMarshallingMethodGenerationDeclaration));
82+
}
83+
84+
[TestMethod]
85+
public void GeneratingHeaderStubsFromNFAppTest()
86+
{
87+
var generatedFile =
88+
File.ReadAllText(
89+
$"{stubPath}\\StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration.h");
90+
91+
Assert.IsTrue(generatedFile.Contains(NativeHeaderMethodGenerationDeclaration));
92+
}
93+
94+
private const string StaticMethodWithoutParameterHeaderGeneration =
95+
@"static void NativeStaticMethod( HRESULT &hr );";
96+
private const string StaticMethodWithoutParameterMarshallGeneration =
97+
@"HRESULT Library_StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration::NativeStaticMethod___STATIC__VOID( CLR_RT_StackFrame& stack )
98+
{
99+
NANOCLR_HEADER(); hr = S_OK;
100+
{
101+
102+
NativeMethodGeneration::NativeStaticMethod( hr );
103+
NANOCLR_CHECK_HRESULT( hr );
104+
105+
}
106+
NANOCLR_NOCLEANUP();
107+
}";
108+
private const string StaticMethodWithoutParameterImplementationGeneration =
109+
@"void NativeMethodGeneration::NativeStaticMethod( HRESULT &hr )
110+
{
111+
112+
(void)hr;
113+
114+
115+
////////////////////////////////
116+
// implementation starts here //
117+
118+
119+
// implementation ends here //
120+
////////////////////////////////
121+
122+
123+
}";
124+
125+
[TestMethod]
126+
public void GeneratingStaticMethodWithoutParams()
127+
{
128+
var generatedHeaderFile =
129+
File.ReadAllText(
130+
$"{stubPath}\\StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration.h");
131+
132+
var generatedMarshallFile =
133+
File.ReadAllText(
134+
$"{stubPath}\\StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration_mshl.cpp");
135+
136+
var generatedImplementationFile =
137+
File.ReadAllText(
138+
$"{stubPath}\\StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration.cpp");
139+
140+
Assert.IsTrue(generatedHeaderFile.Contains(StaticMethodWithoutParameterHeaderGeneration));
141+
Assert.IsTrue(generatedMarshallFile.Contains(StaticMethodWithoutParameterMarshallGeneration));
142+
Assert.IsTrue(generatedImplementationFile.Contains(StaticMethodWithoutParameterImplementationGeneration));
143+
}
144+
145+
private const string StaticMethodHeaderGeneration =
146+
@"static uint8_t NativeStaticMethodReturningByte( char param0, HRESULT &hr );";
147+
private const string StaticMethodMarshallGeneration =
148+
@"HRESULT Library_StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration::NativeStaticMethodReturningByte___STATIC__U1__CHAR( CLR_RT_StackFrame& stack )
149+
{
150+
NANOCLR_HEADER(); hr = S_OK;
151+
{
152+
153+
char param0;
154+
NANOCLR_CHECK_HRESULT( Interop_Marshal_CHAR( stack, 0, param0 ) );
155+
156+
uint8_t retValue = NativeMethodGeneration::NativeStaticMethodReturningByte( param0, hr );
157+
NANOCLR_CHECK_HRESULT( hr );
158+
SetResult_UINT8( stack, retValue );
159+
}
160+
NANOCLR_NOCLEANUP();
161+
}";
162+
private const string StaticMethodImplementationGeneration =
163+
@"uint8_t NativeMethodGeneration::NativeStaticMethodReturningByte( char param0, HRESULT &hr )
164+
{
165+
166+
(void)param0;
167+
(void)hr;
168+
uint8_t retValue = 0;
169+
170+
////////////////////////////////
171+
// implementation starts here //
172+
173+
174+
// implementation ends here //
175+
////////////////////////////////
176+
177+
return retValue;
178+
}";
179+
180+
[TestMethod]
181+
public void GeneratingStaticMethod()
182+
{
183+
var generatedHeaderFile =
184+
File.ReadAllText(
185+
$"{stubPath}\\StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration.h");
186+
187+
var generatedMarshallFile =
188+
File.ReadAllText(
189+
$"{stubPath}\\StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration_mshl.cpp");
190+
191+
var generatedImplementationFile =
192+
File.ReadAllText(
193+
$"{stubPath}\\StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration.cpp");
194+
195+
Assert.IsTrue(generatedHeaderFile.Contains(StaticMethodHeaderGeneration));
196+
Assert.IsTrue(generatedMarshallFile.Contains(StaticMethodMarshallGeneration));
197+
Assert.IsTrue(generatedImplementationFile.Contains(StaticMethodImplementationGeneration));
198+
}
199+
200+
[TestInitialize]
201+
public void GenerateStubs()
38202
{
39203
var loadHints = new Dictionary<string, string>(StringComparer.Ordinal)
40204
{
@@ -50,22 +214,22 @@ public void GeneratingStubsFromNFAppTest()
50214

51215
var fileToParse = TestObjectHelper.GenerationNFAppFullPath;
52216
var fileToCompile = Path.ChangeExtension(fileToParse, "pe");
53-
217+
54218
// get path where stubs will be generated
55-
var stubPath = Path.Combine(
219+
stubPath = Path.Combine(
56220
TestObjectHelper.TestExecutionLocation,
57221
"Stubs");
58-
222+
59223
var assemblyDefinition = AssemblyDefinition.ReadAssembly(
60224
fileToParse,
61225
new ReaderParameters { AssemblyResolver = new LoadHintsAssemblyResolver(loadHints) });
62226

63-
var assemblyBuilder = new nanoAssemblyBuilder(assemblyDefinition, classNamesToExclude, false, false);
227+
var assemblyBuilder = new nanoAssemblyBuilder(assemblyDefinition, classNamesToExclude, false);
64228

65229
using (var stream = File.Open(
66-
Path.ChangeExtension(fileToCompile, "tmp"),
67-
FileMode.Create,
68-
FileAccess.ReadWrite))
230+
Path.ChangeExtension(fileToCompile, "tmp"),
231+
FileMode.Create,
232+
FileAccess.ReadWrite))
69233
using (var writer = new BinaryWriter(stream))
70234
{
71235
assemblyBuilder.Write(GetBinaryWriter(writer));
@@ -87,12 +251,11 @@ public void GeneratingStubsFromNFAppTest()
87251
false);
88252

89253
skeletonGenerator.GenerateSkeleton();
254+
}
90255

91-
// read generated stub file and look for the function declaration
92-
string generatedFile = File.ReadAllText($"{stubPath}\\StubsGenerationTestNFApp_StubsGenerationTestNFApp_NativeMethodGeneration.cpp");
93-
94-
Assert.IsTrue(generatedFile.Contains(NativeMethodGenerationDeclaration));
95-
256+
[TestCleanup]
257+
public void DeleteStubs()
258+
{
96259
Directory.Delete(stubPath, true);
97260
}
98261

MetadataProcessor.Tests/StubsGenerationTestNFApp/NativeMethodGeneration.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,11 @@ public void Method()
2323

2424
[MethodImpl(MethodImplOptions.InternalCall)]
2525
private extern void NativeMethodWithReferenceParameters(ref byte refByteParam, ref ushort refUshortParam);
26+
27+
[MethodImpl(MethodImplOptions.InternalCall)]
28+
private static extern void NativeStaticMethod();
29+
30+
[MethodImpl(MethodImplOptions.InternalCall)]
31+
private static extern byte NativeStaticMethodReturningByte(char charParam);
2632
}
2733
}

MetadataProcessor.Tests/StubsGenerationTestNFApp/StubsGenerationTestNFApp.nfproj

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
<AssemblyName>StubsGenerationTestNFApp</AssemblyName>
1717
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
1818
</PropertyGroup>
19-
<PropertyGroup Label="nanoFramework">
20-
<NFMDP_GENERATE_STUBS>True</NFMDP_GENERATE_STUBS>
21-
</PropertyGroup>
2219
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
2320
<ItemGroup>
2421
<Compile Include="NativeMethodGeneration.cs" />

0 commit comments

Comments
 (0)