@@ -147,6 +147,7 @@ impl WorldGenerator for CSharp {
147147 gen. import ( & resolve. name_world_key ( key) , func) ;
148148 }
149149
150+ gen. add_import_return_area ( ) ;
150151 gen. add_interface_fragment ( false ) ;
151152 }
152153
@@ -183,6 +184,7 @@ impl WorldGenerator for CSharp {
183184 gen. export ( func, Some ( key) ) ;
184185 }
185186
187+ gen. add_export_return_area ( ) ;
186188 gen. add_interface_fragment ( true ) ;
187189 Ok ( ( ) )
188190 }
@@ -591,6 +593,99 @@ impl InterfaceGenerator<'_> {
591593 } ) ;
592594 }
593595
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+
594689 fn add_world_fragment ( self ) {
595690 self . gen . world_fragments . push ( InterfaceFragment {
596691 csharp_src : self . src ,
@@ -677,39 +772,9 @@ impl InterfaceGenerator<'_> {
677772 "#
678773 ) ;
679774
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-
709775 uwrite ! (
710776 self . csharp_interop_src,
711777 r#"
712- {ret_struct_type}
713778 internal static unsafe {result_type} {camel_name}({params})
714779 {{
715780 {src}
@@ -1460,7 +1525,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
14601525 self . src,
14611526 "
14621527 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} );"
14641529 ) ;
14651530
14661531 //TODO: Oppertunity to optimize and not reallocate every call
@@ -1469,7 +1534,7 @@ impl Bindgen for FunctionBindgen<'_, '_> {
14691534 } else {
14701535 results. push ( format ! ( "{interop_string}.ToInt32()" ) ) ;
14711536 }
1472- results. push ( format ! ( "length" ) ) ;
1537+ results. push ( format ! ( "length{result_var} " ) ) ;
14731538
14741539 self . gen . gen . needs_interop_string = true ;
14751540 }
0 commit comments