1212using WindowsRuntime . ProjectionWriter . Resolvers ;
1313using WindowsRuntime . ProjectionWriter . Writers ;
1414
15+ #pragma warning disable IDE0045
16+
1517namespace WindowsRuntime . ProjectionWriter . Factories ;
1618
1719internal static partial class ConstructorFactory
@@ -296,13 +298,14 @@ private sealed class {{callbackName}} : {{baseClass}}
296298 string raw = p . GetRawName ( ) ;
297299 string callName = IdentifierEscaping . EscapeIdentifier ( raw ) ;
298300 ArrayTempNames names = new ( raw ) ;
301+ string storageT = AbiTypeHelpers . GetArrayElementStorageType ( context , szArr . BaseType ) ;
299302 writer . WriteLine ( ) ;
300303 writer . WriteLine ( isMultiline : true , $$ """
301- Unsafe.SkipInit(out InlineArray16<nint > {{ names . InlineArray }} );
302- nint [] {{ names . ArrayFromPool }} = null;
303- Span<nint > {{ names . Span }} = {{ callName }} .Length <= 16
304+ Unsafe.SkipInit(out InlineArray16<{{ storageT }} > {{ names . InlineArray }} );
305+ {{ storageT }} [] {{ names . ArrayFromPool }} = null;
306+ Span<{{ storageT }} > {{ names . Span }} = {{ callName }} .Length <= 16
304307 ? {{ names . InlineArray }} [..{{ callName }} .Length]
305- : ({{ names . ArrayFromPool }} = global::System.Buffers.ArrayPool<nint >.Shared.Rent({{ callName }} .Length));
308+ : ({{ names . ArrayFromPool }} = global::System.Buffers.ArrayPool<{{ storageT }} >.Shared.Rent({{ callName }} .Length));
306309 """ ) ;
307310
308311 if ( szArr . BaseType . IsString ( ) )
@@ -467,7 +470,7 @@ private sealed class {{callbackName}} : {{baseClass}}
467470 }
468471 }
469472
470- // Emit CopyToUnmanaged for non-blittable PassArray params.
473+ // Emit ' CopyToUnmanaged' for non-blittable PassArray params
471474 for ( int i = 0 ; i < paramCount ; i ++ )
472475 {
473476 ParameterInfo p = sig . Parameters [ i ] ;
@@ -505,14 +508,35 @@ private sealed class {{callbackName}} : {{baseClass}}
505508 else
506509 {
507510 IndentedTextWriterCallback elementProjected = TypedefNameWriter . WriteProjectionType ( context , TypeSemanticsFactory . Get ( szArr . BaseType ) ) ;
511+
512+ // Data pointer type must match the array marshaller's 'CopyToUnmanaged' signature
513+ string dataParamType ;
514+
515+ if ( context . AbiTypeKindResolver . IsMappedAbiValueType ( szArr . BaseType ) )
516+ {
517+ dataParamType = AbiTypeHelpers . GetMappedAbiTypeName ( szArr . BaseType ) + "*" ;
518+ }
519+ else if ( szArr . BaseType . IsHResultException ( ) )
520+ {
521+ dataParamType = "global::ABI.System.Exception*" ;
522+ }
523+ else if ( context . AbiTypeKindResolver . IsNonBlittableStruct ( szArr . BaseType ) )
524+ {
525+ dataParamType = AbiTypeHelpers . GetAbiStructTypeName ( context , szArr . BaseType ) + "*" ;
526+ }
527+ else
528+ {
529+ dataParamType = "void**" ;
530+ }
531+
508532 UnsafeAccessorFactory . EmitStaticMethod (
509533 writer ,
510534 accessName : "CopyToUnmanaged" ,
511535 returnType : "void" ,
512536 functionName : $ "CopyToUnmanaged_{ raw } ",
513537 interopType : ArrayElementEncoder . GetArrayMarshallerInteropPath ( szArr . BaseType ) ,
514- parameterList : $ "ReadOnlySpan<{ elementProjected . Format ( ) } > span, uint length, void** data") ;
515- writer . WriteLine ( $ "CopyToUnmanaged_{ raw } (null, { pname } , (uint){ pname } .Length, (void** )_{ raw } );") ;
538+ parameterList : $ "ReadOnlySpan<{ elementProjected . Format ( ) } > span, uint length, { dataParamType } data") ;
539+ writer . WriteLine ( $ "CopyToUnmanaged_{ raw } (null, { pname } , (uint){ pname } .Length, ({ dataParamType } )_{ raw } );") ;
516540 }
517541 }
518542
@@ -534,7 +558,7 @@ private sealed class {{callbackName}} : {{baseClass}}
534558
535559 if ( isComposable )
536560 {
537- // Composable extras: baseInterface (void*), out innerInterface (void**)
561+ // Composable extras: ' baseInterface (void*), out innerInterface (void**)'
538562 writer . Write ( "void*, void**, " ) ;
539563 }
540564
@@ -555,12 +579,12 @@ private sealed class {{callbackName}} : {{baseClass}}
555579 continue ;
556580 }
557581
558- // For enums, cast to underlying type. For bool, cast to byte. For char, cast to ushort.
559- // For string params, use the marshalled HString from the fixed block.
560- // For runtime class / object / generic instance params, use __<name>.GetThisPtrUnsafe().
582+ // For enums, cast to underlying type. For ' bool' , cast to ' byte' . For ' char' , cast to ' ushort' .
583+ // For ' string' params, use the marshalled 'HSTRING' from the fixed block.
584+ // For runtime class / ' object' / generic instance params, use ' __<name>.GetThisPtrUnsafe()' .
561585 if ( context . AbiTypeKindResolver . IsEnumType ( p . Type ) )
562586 {
563- // No cast needed: function pointer signature uses the projected enum type.
587+ // No cast needed: function pointer signature uses the projected enum type
564588 writer . Write ( pname ) ;
565589 }
566590 else if ( p . Type is CorLibTypeSignature corlibBool &&
@@ -605,7 +629,7 @@ private sealed class {{callbackName}} : {{baseClass}}
605629
606630 if ( isComposable )
607631 {
608- // Pass __baseInterface.GetThisPtrUnsafe() and &__innerInterface.
632+ // Pass ' __baseInterface.GetThisPtrUnsafe()' and ' &__innerInterface'
609633 writer . Write ( isMultiline : true , """
610634 ,
611635 __baseInterface.GetThisPtrUnsafe(),
@@ -623,7 +647,7 @@ private sealed class {{callbackName}} : {{baseClass}}
623647
624648 writer . WriteLine ( "retval = __retval;" ) ;
625649
626- // Close fixed blocks (innermost first).
650+ // Close fixed blocks (innermost first)
627651 for ( int i = 0 ; i < fixedNesting ; i ++ )
628652 {
629653 writer . DecreaseIndent ( ) ;
@@ -642,8 +666,8 @@ private sealed class {{callbackName}} : {{baseClass}}
642666 """ ) ;
643667 writer . IncreaseIndent ( ) ;
644668
645- // Dispose pre-marshalled ABI struct input locals (frees any HSTRING / boxed
646- // reference fields the per-field ConvertToUnmanaged may have allocated).
669+ // Dispose pre-marshalled ABI struct input locals (frees any ' HSTRING' / boxed
670+ // reference fields the per-field ' ConvertToUnmanaged' may have allocated).
647671 for ( int i = 0 ; i < paramCount ; i ++ )
648672 {
649673 ParameterInfo p = sig . Parameters [ i ] ;
@@ -677,9 +701,28 @@ private sealed class {{callbackName}} : {{baseClass}}
677701 continue ;
678702 }
679703
704+ // Mapped value types ('DateTime'/'TimeSpan') need no disposal or pool return
705+ if ( context . AbiTypeKindResolver . IsMappedAbiValueType ( szArr . BaseType ) )
706+ {
707+ continue ;
708+ }
709+
680710 string raw = p . GetRawName ( ) ;
681711 ArrayTempNames names = new ( raw ) ;
682712
713+ if ( szArr . BaseType . IsHResultException ( ) )
714+ {
715+ // 'HResult' ABI is just an 'int': no per-element 'Dispose', only the pool return
716+ writer . WriteLine ( ) ;
717+ writer . WriteLine ( isMultiline : true , $$ """
718+ if ({{ names . ArrayFromPool }} is not null)
719+ {
720+ global::System.Buffers.ArrayPool<global::ABI.System.Exception>.Shared.Return({{ names . ArrayFromPool }} );
721+ }
722+ """ ) ;
723+ continue ;
724+ }
725+
683726 if ( szArr . BaseType . IsString ( ) )
684727 {
685728 writer . WriteLine ( ) ;
@@ -699,27 +742,49 @@ private sealed class {{callbackName}} : {{baseClass}}
699742 }
700743 else
701744 {
745+ // Complex structs use a typed <ABI struct>* (no cast), ref types use 'void**'
746+ string disposeDataParamType ;
747+ string fixedPtrType ;
748+ string disposeCastType ;
749+
750+ if ( context . AbiTypeKindResolver . IsNonBlittableStruct ( szArr . BaseType ) )
751+ {
752+ string abiStructName = AbiTypeHelpers . GetAbiStructTypeName ( context , szArr . BaseType ) ;
753+ disposeDataParamType = abiStructName + "* data" ;
754+ fixedPtrType = abiStructName + "*" ;
755+ disposeCastType = string . Empty ;
756+ }
757+ else
758+ {
759+ disposeDataParamType = "void** data" ;
760+ fixedPtrType = "void*" ;
761+ disposeCastType = "(void**)" ;
762+ }
763+
702764 writer . WriteLine ( ) ;
703765 UnsafeAccessorFactory . EmitStaticMethod (
704766 writer ,
705767 accessName : "Dispose" ,
706768 returnType : "void" ,
707769 functionName : $ "Dispose_{ raw } ",
708770 interopType : ArrayElementEncoder . GetArrayMarshallerInteropPath ( szArr . BaseType ) ,
709- parameterList : "uint length, void** data " ) ;
771+ parameterList : $ "uint length, { disposeDataParamType } ") ;
710772 writer . WriteLine ( ) ;
711773 writer . WriteLine ( isMultiline : true , $$ """
712- fixed(void* _{{ raw }} = {{ names . Span }} )
774+ fixed({{ fixedPtrType }} _{{ raw }} = {{ names . Span }} )
713775 {
714- Dispose_{{ raw }} (null, (uint) {{ names . Span }} .Length, (void**) _{{ raw }} );
776+ Dispose_{{ raw }} (null, (uint) {{ names . Span }} .Length, {{ disposeCastType }} _{{ raw }} );
715777 }
716778 """ ) ;
717779 }
780+
781+ // Pool storage type matches the 'InlineArray16<storageT>' setup
782+ string poolStorageT = AbiTypeHelpers . GetArrayElementStorageType ( context , szArr . BaseType ) ;
718783 writer . WriteLine ( ) ;
719784 writer . WriteLine ( isMultiline : true , $$ """
720785 if ({{ names . ArrayFromPool }} is not null)
721786 {
722- global::System.Buffers.ArrayPool<nint >.Shared.Return({{ names . ArrayFromPool }} );
787+ global::System.Buffers.ArrayPool<{{ poolStorageT }} >.Shared.Return({{ names . ArrayFromPool }} );
723788 }
724789 """ ) ;
725790 }
0 commit comments