@@ -145,6 +145,42 @@ impl WorldGenerator for CSharp {
145
145
gen. import ( & resolve. name_world_key ( key) , func) ;
146
146
}
147
147
148
+ let mut ret_struct_type = String :: new ( ) ;
149
+ if gen. gen . return_area_size > 0 {
150
+ uwrite ! (
151
+ ret_struct_type,
152
+ r#"
153
+ private unsafe struct ReturnArea
154
+ {{
155
+ private int GetS32(IntPtr ptr, int offset)
156
+ {{
157
+ var span = new Span<byte>((void*)ptr, {});
158
+
159
+ return BitConverter.ToInt32(span.Slice(offset, 4));
160
+ }}
161
+
162
+ public string GetUTF8String(IntPtr ptr)
163
+ {{
164
+ return Encoding.UTF8.GetString((byte*)GetS32(ptr, 0), GetS32(ptr, 4));
165
+ }}
166
+
167
+ }}
168
+
169
+ [ThreadStatic]
170
+ [FixedAddressValueType]
171
+ private static ReturnArea returnArea;
172
+ "# ,
173
+ gen . gen . return_area_size
174
+ ) ;
175
+ }
176
+
177
+ uwrite ! (
178
+ gen . csharp_interop_src,
179
+ r#"
180
+ {ret_struct_type}
181
+ "#
182
+ ) ;
183
+
148
184
gen. add_interface_fragment ( false ) ;
149
185
}
150
186
@@ -181,6 +217,59 @@ impl WorldGenerator for CSharp {
181
217
gen. export ( func, Some ( key) ) ;
182
218
}
183
219
220
+ // Declare a statically-allocated return area, if needed. We only do
221
+ // this for export bindings, because import bindings allocate their
222
+ // return-area on the stack.
223
+ if gen. gen . return_area_size > 0 {
224
+ let mut ret_area_str = String :: new ( ) ;
225
+
226
+ uwrite ! (
227
+ ret_area_str,
228
+ "
229
+ [InlineArray({})]
230
+ [StructLayout(LayoutKind.Sequential, Pack = {})]
231
+ private struct ReturnArea
232
+ {{
233
+ private byte buffer;
234
+
235
+ private int GetS32(int offset)
236
+ {{
237
+ ReadOnlySpan<byte> span = this;
238
+
239
+ return BitConverter.ToInt32(span.Slice(offset, 4));
240
+ }}
241
+
242
+ public void SetS32(int offset, int value)
243
+ {{
244
+ Span<byte> span = this;
245
+
246
+ BitConverter.TryWriteBytes(span.Slice(offset), value);
247
+ }}
248
+
249
+ internal unsafe int AddrOfBuffer()
250
+ {{
251
+ fixed(byte* ptr = &buffer)
252
+ {{
253
+ return (int)ptr;
254
+ }}
255
+ }}
256
+
257
+ public unsafe string GetUTF8String(int p0, int p1)
258
+ {{
259
+ return Encoding.UTF8.GetString((byte*)p0, p1);
260
+ }}
261
+ }}
262
+
263
+ [ThreadStatic]
264
+ private static ReturnArea returnArea = default;
265
+ " ,
266
+ gen . gen . return_area_size,
267
+ gen . gen . return_area_align,
268
+ ) ;
269
+
270
+ gen. csharp_interop_src . push_str ( & ret_area_str) ;
271
+ }
272
+
184
273
gen. add_interface_fragment ( true ) ;
185
274
Ok ( ( ) )
186
275
}
@@ -675,39 +764,9 @@ impl InterfaceGenerator<'_> {
675
764
"#
676
765
) ;
677
766
678
- let mut ret_struct_type = String :: new ( ) ;
679
- if self . gen . return_area_size > 0 {
680
- uwrite ! (
681
- ret_struct_type,
682
- r#"
683
- private unsafe struct ReturnArea
684
- {{
685
- private int GetS32(IntPtr ptr, int offset)
686
- {{
687
- var span = new Span<byte>((void*)ptr, {});
688
-
689
- return BitConverter.ToInt32(span.Slice(offset, 4));
690
- }}
691
-
692
- public string GetUTF8String(IntPtr ptr)
693
- {{
694
- return Encoding.UTF8.GetString((byte*)GetS32(ptr, 0), GetS32(ptr, 4));
695
- }}
696
-
697
- }}
698
-
699
- [ThreadStatic]
700
- [FixedAddressValueType]
701
- private static ReturnArea returnArea;
702
- "# ,
703
- self . gen . return_area_size
704
- ) ;
705
- }
706
-
707
767
uwrite ! (
708
768
self . csharp_interop_src,
709
769
r#"
710
- {ret_struct_type}
711
770
internal static unsafe {result_type} {camel_name}({params})
712
771
{{
713
772
{src}
@@ -1458,7 +1517,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1458
1517
self . src,
1459
1518
"
1460
1519
var {result_var} = {op};
1461
- IntPtr {interop_string} = InteropString.FromString({result_var}, out int length);"
1520
+ IntPtr {interop_string} = InteropString.FromString({result_var}, out int length{result_var} );"
1462
1521
) ;
1463
1522
1464
1523
//TODO: Oppertunity to optimize and not reallocate every call
@@ -1467,7 +1526,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1467
1526
} else {
1468
1527
results. push ( format ! ( "{interop_string}.ToInt32()" ) ) ;
1469
1528
}
1470
- results. push ( format ! ( "length" ) ) ;
1529
+ results. push ( format ! ( "length{result_var} " ) ) ;
1471
1530
1472
1531
self . gen . gen . needs_interop_string = true ;
1473
1532
}
0 commit comments