@@ -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
}
@@ -662,39 +751,9 @@ impl InterfaceGenerator<'_> {
662
751
"#
663
752
) ;
664
753
665
- let mut ret_struct_type = String :: new ( ) ;
666
- if self . gen . return_area_size > 0 {
667
- uwrite ! (
668
- ret_struct_type,
669
- r#"
670
- private unsafe struct ReturnArea
671
- {{
672
- private int GetS32(IntPtr ptr, int offset)
673
- {{
674
- var span = new Span<byte>((void*)ptr, {});
675
-
676
- return BitConverter.ToInt32(span.Slice(offset, 4));
677
- }}
678
-
679
- public string GetUTF8String(IntPtr ptr)
680
- {{
681
- return Encoding.UTF8.GetString((byte*)GetS32(ptr, 0), GetS32(ptr, 4));
682
- }}
683
-
684
- }}
685
-
686
- [ThreadStatic]
687
- [FixedAddressValueType]
688
- private static ReturnArea returnArea;
689
- "# ,
690
- self . gen . return_area_size
691
- ) ;
692
- }
693
-
694
754
uwrite ! (
695
755
self . csharp_interop_src,
696
756
r#"
697
- {ret_struct_type}
698
757
internal static unsafe {result_type} {camel_name}({params})
699
758
{{
700
759
{src}
@@ -1440,7 +1499,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1440
1499
self . src,
1441
1500
"
1442
1501
var {result_var} = {op};
1443
- IntPtr {interop_string} = InteropString.FromString({result_var}, out int length);"
1502
+ IntPtr {interop_string} = InteropString.FromString({result_var}, out int length{result_var} );"
1444
1503
) ;
1445
1504
1446
1505
//TODO: Oppertunity to optimize and not reallocate every call
@@ -1449,7 +1508,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1449
1508
} else {
1450
1509
results. push ( format ! ( "{interop_string}.ToInt32()" ) ) ;
1451
1510
}
1452
- results. push ( format ! ( "length" ) ) ;
1511
+ results. push ( format ! ( "length{result_var} " ) ) ;
1453
1512
1454
1513
self . gen . gen . needs_interop_string = true ;
1455
1514
}
0 commit comments