@@ -147,6 +147,7 @@ impl WorldGenerator for CSharp {
147
147
gen. import ( & resolve. name_world_key ( key) , func) ;
148
148
}
149
149
150
+ gen. add_import_return_area ( ) ;
150
151
gen. add_interface_fragment ( false ) ;
151
152
}
152
153
@@ -183,6 +184,7 @@ impl WorldGenerator for CSharp {
183
184
gen. export ( func, Some ( key) ) ;
184
185
}
185
186
187
+ gen. add_export_return_area ( ) ;
186
188
gen. add_interface_fragment ( true ) ;
187
189
Ok ( ( ) )
188
190
}
@@ -591,6 +593,99 @@ impl InterfaceGenerator<'_> {
591
593
} ) ;
592
594
}
593
595
596
+ fn add_import_return_area ( & mut self ) {
597
+ let mut ret_struct_type = String :: new ( ) ;
598
+ if self . gen . return_area_size > 0 {
599
+ uwrite ! (
600
+ ret_struct_type,
601
+ r#"
602
+ private unsafe struct ReturnArea
603
+ {{
604
+ private int GetS32(IntPtr ptr, int offset)
605
+ {{
606
+ var span = new Span<byte>((void*)ptr, {});
607
+
608
+ return BitConverter.ToInt32(span.Slice(offset, 4));
609
+ }}
610
+
611
+ public string GetUTF8String(IntPtr ptr)
612
+ {{
613
+ return Encoding.UTF8.GetString((byte*)GetS32(ptr, 0), GetS32(ptr, 4));
614
+ }}
615
+
616
+ }}
617
+
618
+ [ThreadStatic]
619
+ [FixedAddressValueType]
620
+ private static ReturnArea returnArea;
621
+ "# ,
622
+ self . gen . return_area_size
623
+ ) ;
624
+ }
625
+
626
+ uwrite ! (
627
+ self . csharp_interop_src,
628
+ r#"
629
+ {ret_struct_type}
630
+ "#
631
+ ) ;
632
+ }
633
+
634
+ fn add_export_return_area ( & mut self ) {
635
+ // Declare a statically-allocated return area, if needed. We only do
636
+ // this for export bindings, because import bindings allocate their
637
+ // return-area on the stack.
638
+ if self . gen . return_area_size > 0 {
639
+ let mut ret_area_str = String :: new ( ) ;
640
+
641
+ uwrite ! (
642
+ ret_area_str,
643
+ "
644
+ [InlineArray({})]
645
+ [StructLayout(LayoutKind.Sequential, Pack = {})]
646
+ private struct ReturnArea
647
+ {{
648
+ private byte buffer;
649
+
650
+ private int GetS32(int offset)
651
+ {{
652
+ ReadOnlySpan<byte> span = this;
653
+
654
+ return BitConverter.ToInt32(span.Slice(offset, 4));
655
+ }}
656
+
657
+ public void SetS32(int offset, int value)
658
+ {{
659
+ Span<byte> span = this;
660
+
661
+ BitConverter.TryWriteBytes(span.Slice(offset), value);
662
+ }}
663
+
664
+ internal unsafe int AddrOfBuffer()
665
+ {{
666
+ fixed(byte* ptr = &buffer)
667
+ {{
668
+ return (int)ptr;
669
+ }}
670
+ }}
671
+
672
+ public unsafe string GetUTF8String(int p0, int p1)
673
+ {{
674
+ return Encoding.UTF8.GetString((byte*)p0, p1);
675
+ }}
676
+ }}
677
+
678
+ [ThreadStatic]
679
+ private static ReturnArea returnArea = default;
680
+ " ,
681
+ self . gen . return_area_size,
682
+ self . gen . return_area_align,
683
+ ) ;
684
+
685
+ self . csharp_interop_src . push_str ( & ret_area_str) ;
686
+ }
687
+ }
688
+
594
689
fn add_world_fragment ( self ) {
595
690
self . gen . world_fragments . push ( InterfaceFragment {
596
691
csharp_src : self . src ,
@@ -677,39 +772,9 @@ impl InterfaceGenerator<'_> {
677
772
"#
678
773
) ;
679
774
680
- let mut ret_struct_type = String :: new ( ) ;
681
- if self . gen . return_area_size > 0 {
682
- uwrite ! (
683
- ret_struct_type,
684
- r#"
685
- private unsafe struct ReturnArea
686
- {{
687
- private int GetS32(IntPtr ptr, int offset)
688
- {{
689
- var span = new Span<byte>((void*)ptr, {});
690
-
691
- return BitConverter.ToInt32(span.Slice(offset, 4));
692
- }}
693
-
694
- public string GetUTF8String(IntPtr ptr)
695
- {{
696
- return Encoding.UTF8.GetString((byte*)GetS32(ptr, 0), GetS32(ptr, 4));
697
- }}
698
-
699
- }}
700
-
701
- [ThreadStatic]
702
- [FixedAddressValueType]
703
- private static ReturnArea returnArea;
704
- "# ,
705
- self . gen . return_area_size
706
- ) ;
707
- }
708
-
709
775
uwrite ! (
710
776
self . csharp_interop_src,
711
777
r#"
712
- {ret_struct_type}
713
778
internal static unsafe {result_type} {camel_name}({params})
714
779
{{
715
780
{src}
@@ -1460,7 +1525,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1460
1525
self . src,
1461
1526
"
1462
1527
var {result_var} = {op};
1463
- IntPtr {interop_string} = InteropString.FromString({result_var}, out int length);"
1528
+ IntPtr {interop_string} = InteropString.FromString({result_var}, out int length{result_var} );"
1464
1529
) ;
1465
1530
1466
1531
//TODO: Oppertunity to optimize and not reallocate every call
@@ -1469,7 +1534,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
1469
1534
} else {
1470
1535
results. push ( format ! ( "{interop_string}.ToInt32()" ) ) ;
1471
1536
}
1472
- results. push ( format ! ( "length" ) ) ;
1537
+ results. push ( format ! ( "length{result_var} " ) ) ;
1473
1538
1474
1539
self . gen . gen . needs_interop_string = true ;
1475
1540
}
0 commit comments