@@ -22,9 +22,7 @@ pub(crate) struct FunctionBindgen<'a, 'b> {
2222 block_storage : Vec < BlockStorage > ,
2323 blocks : Vec < Block > ,
2424 payloads : Vec < String > ,
25- pub ( crate ) needs_cleanup_list : bool ,
26- needs_native_alloc_list : bool ,
27- cleanup : Vec < Cleanup > ,
25+ pub ( crate ) needs_cleanup : bool ,
2826 import_return_pointer_area_size : usize ,
2927 import_return_pointer_area_align : usize ,
3028 pub ( crate ) resource_drops : Vec < ( String , String ) > ,
@@ -55,9 +53,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
5553 block_storage : Vec :: new ( ) ,
5654 blocks : Vec :: new ( ) ,
5755 payloads : Vec :: new ( ) ,
58- needs_cleanup_list : false ,
59- needs_native_alloc_list : false ,
60- cleanup : Vec :: new ( ) ,
56+ needs_cleanup : false ,
6157 import_return_pointer_area_size : 0 ,
6258 import_return_pointer_area_align : 0 ,
6359 resource_drops : Vec :: new ( ) ,
@@ -729,16 +725,17 @@ impl Bindgen for FunctionBindgen<'_, '_> {
729725 // Despite the name GCHandle.Alloc here this does not actually allocate memory on the heap.
730726 // It pins the array with the garbage collector so that it can be passed to unmanaged code.
731727 // It is required to free the pin after use which is done in the Cleanup section.
728+ self . needs_cleanup = true ;
732729 uwrite ! (
733730 self . src,
734731 "
735732 var {handle} = GCHandle.Alloc({list}, GCHandleType.Pinned);
736733 var {ptr} = {handle}.AddrOfPinnedObject();
734+ cleanups.Add(()=> {handle}.Free());
737735 "
738736 ) ;
739737 results. push ( format ! ( "{ptr}" ) ) ;
740738 results. push ( format ! ( "({list}).Length" ) ) ;
741- self . cleanup . push ( Cleanup { address : handle } ) ;
742739 }
743740 Direction :: Export => {
744741 let address = self . locals . tmp ( "address" ) ;
@@ -756,9 +753,12 @@ impl Bindgen for FunctionBindgen<'_, '_> {
756753 ) ;
757754
758755 if realloc. is_none ( ) {
759- self . cleanup . push ( Cleanup {
760- address : gc_handle. clone ( ) ,
761- } ) ;
756+ self . needs_cleanup = true ;
757+ uwrite ! (
758+ self . src,
759+ "
760+ cleanups.Add(()=> {gc_handle}.Free());
761+ " ) ;
762762 }
763763 results. push ( format ! ( "((IntPtr)({address})).ToInt32()" ) ) ;
764764 results. push ( format ! ( "{list}.Length" ) ) ;
@@ -786,22 +786,39 @@ impl Bindgen for FunctionBindgen<'_, '_> {
786786 Instruction :: StringLower { realloc } => {
787787 let op = & operands[ 0 ] ;
788788 let interop_string = self . locals . tmp ( "interopString" ) ;
789- let result_var = self . locals . tmp ( "result" ) ;
789+ let utf8_bytes = self . locals . tmp ( "utf8Bytes" ) ;
790+ let length = self . locals . tmp ( "length" ) ;
791+ let gc_handle = self . locals . tmp ( "gcHandle" ) ;
790792 uwriteln ! (
791793 self . src,
792794 "
793- var {result_var} = {op};
794- IntPtr {interop_string} = InteropString.FromString({result_var}, out int length{result_var});"
795+ var {utf8_bytes} = Encoding.UTF8.GetBytes({op});
796+ var {length} = {utf8_bytes}.Length;
797+ var {gc_handle} = GCHandle.Alloc({utf8_bytes}, GCHandleType.Pinned);
798+ var {interop_string} = {gc_handle}.AddrOfPinnedObject();
799+ "
795800 ) ;
796801
797802 if realloc. is_none ( ) {
798803 results. push ( format ! ( "{interop_string}.ToInt32()" ) ) ;
804+ self . needs_cleanup = true ;
805+ uwrite ! (
806+ self . src,
807+ "
808+ cleanups.Add(()=> {gc_handle}.Free());
809+ " ) ;
799810 } else {
800811 results. push ( format ! ( "{interop_string}.ToInt32()" ) ) ;
801812 }
802- results. push ( format ! ( "length{result_var }" ) ) ;
813+ results. push ( format ! ( "{length }" ) ) ;
803814
804- self . interface_gen . csharp_gen . needs_interop_string = true ;
815+ if FunctionKind :: Freestanding == * self . kind || self . interface_gen . direction == Direction :: Export {
816+ self . interface_gen . require_interop_using ( "System.Text" ) ;
817+ self . interface_gen . require_interop_using ( "System.Runtime.InteropServices" ) ;
818+ } else {
819+ self . interface_gen . require_using ( "System.Text" ) ;
820+ self . interface_gen . require_using ( "System.Runtime.InteropServices" ) ;
821+ }
805822 }
806823
807824 Instruction :: StringLift { .. } => {
@@ -835,14 +852,14 @@ impl Bindgen for FunctionBindgen<'_, '_> {
835852 let buffer_size = self . locals . tmp ( "bufferSize" ) ;
836853 //TODO: wasm64
837854 let align = self . interface_gen . csharp_gen . sizes . align ( element) . align_wasm32 ( ) ;
838- self . needs_native_alloc_list = true ;
839855
856+ self . needs_cleanup = true ;
840857 uwrite ! (
841858 self . src,
842859 "
843860 var {buffer_size} = {size} * (nuint){list}.Count;
844861 var {address} = NativeMemory.AlignedAlloc({buffer_size}, {align});
845- nativeAllocs .Add((IntPtr) {address});
862+ cleanups .Add(()=> NativeMemory.AlignedFree( {address}) );
846863
847864 for (int {index} = 0; {index} < {list}.Count; ++{index}) {{
848865 {ty} {block_element} = {list}[{index}];
@@ -988,19 +1005,15 @@ impl Bindgen for FunctionBindgen<'_, '_> {
9881005 }
9891006
9901007 Instruction :: Return { amt : _, func } => {
991- for Cleanup { address } in & self . cleanup {
992- uwriteln ! ( self . src, "{address}.Free();" ) ;
993- }
994-
995- if self . needs_native_alloc_list {
996- self . src . insert_str ( 0 , "var nativeAllocs = new List<IntPtr>();
1008+ if self . needs_cleanup {
1009+ self . src . insert_str ( 0 , "var cleanups = new List<Action>();
9971010 " ) ;
9981011
9991012 uwriteln ! ( self . src, "\
1000- foreach (var nativeAlloc in nativeAllocs )
1001- {{
1002- NativeMemory.AlignedFree((void*)nativeAlloc );
1003- }}" ) ;
1013+ foreach (var cleanup in cleanups )
1014+ {{
1015+ cleanup( );
1016+ }}" ) ;
10041017 }
10051018
10061019 if !matches ! ( ( self . interface_gen. direction, self . kind) , ( Direction :: Import , FunctionKind :: Constructor ( _) ) ) {
@@ -1204,7 +1217,6 @@ impl Bindgen for FunctionBindgen<'_, '_> {
12041217 body : mem:: take ( & mut self . src ) ,
12051218 element : self . locals . tmp ( "element" ) ,
12061219 base : self . locals . tmp ( "basePtr" ) ,
1207- cleanup : mem:: take ( & mut self . cleanup ) ,
12081220 } ) ;
12091221 }
12101222
@@ -1213,19 +1225,8 @@ impl Bindgen for FunctionBindgen<'_, '_> {
12131225 body,
12141226 element,
12151227 base,
1216- cleanup,
12171228 } = self . block_storage . pop ( ) . unwrap ( ) ;
12181229
1219- if !self . cleanup . is_empty ( ) {
1220- //self.needs_cleanup_list = true;
1221-
1222- for Cleanup { address } in & self . cleanup {
1223- uwriteln ! ( self . src, "{address}.Free();" ) ;
1224- }
1225- }
1226-
1227- self . cleanup = cleanup;
1228-
12291230 self . blocks . push ( Block {
12301231 body : mem:: replace ( & mut self . src , body) ,
12311232 results : mem:: take ( operands) ,
@@ -1304,15 +1305,10 @@ struct Block {
13041305 base : String ,
13051306}
13061307
1307- struct Cleanup {
1308- address : String ,
1309- }
1310-
13111308struct BlockStorage {
13121309 body : String ,
13131310 element : String ,
13141311 base : String ,
1315- cleanup : Vec < Cleanup > ,
13161312}
13171313
13181314#[ derive( Clone ) ]
0 commit comments