@@ -153,7 +153,7 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
153
153
154
154
if ( isRefParam )
155
155
{
156
- Context . Return . Write ( "_{0}" , param . Name ) ;
156
+ Context . Return . Write ( Generator . GeneratedIdentifier ( param . Name ) ) ;
157
157
return true ;
158
158
}
159
159
@@ -172,9 +172,11 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
172
172
}
173
173
else
174
174
{
175
- var templateParameter = type as TemplateParameterType ;
176
- if ( templateParameter != null )
177
- Context . Return . Write ( $ "({ templateParameter . Parameter . Name } ) (object) *") ;
175
+ var substitution = pointer . Pointee . Desugar (
176
+ resolveTemplateSubstitution : false ) as TemplateParameterSubstitutionType ;
177
+ if ( substitution != null )
178
+ Context . Return . Write ( $@ "({
179
+ substitution . ReplacedParameter . Parameter . Name } ) (object) *" ) ;
178
180
}
179
181
}
180
182
@@ -492,49 +494,6 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
492
494
if ( ! VisitType ( pointer , quals ) )
493
495
return false ;
494
496
495
- var qualifiedPointer = new QualifiedType ( pointer , quals ) ;
496
-
497
- var templateSubstitution = pointer . Pointee as TemplateParameterSubstitutionType ;
498
- PointerType realPointer = null ;
499
- if ( templateSubstitution != null )
500
- realPointer = templateSubstitution . Replacement . Type . Desugar ( ) as PointerType ;
501
- realPointer = realPointer ?? pointer ;
502
- if ( Context . Function != null &&
503
- ( realPointer . IsPrimitiveTypeConvertibleToRef ( ) ||
504
- ( templateSubstitution != null && realPointer . Pointee . IsEnumType ( ) ) ) &&
505
- Context . MarshalKind != MarshalKind . VTableReturnValue )
506
- {
507
- var refParamPtr = $ "__refParamPtr{ Context . ParameterIndex } ";
508
- if ( templateSubstitution != null )
509
- {
510
- var castParam = $ "__{ Context . Parameter . Name } { Context . ParameterIndex } ";
511
- Context . Before . Write ( $ "var { castParam } = ({ templateSubstitution } ) ") ;
512
- if ( realPointer != pointer )
513
- Context . Before . Write ( $ "({ CSharpTypePrinter . IntPtrType } ) ") ;
514
- Context . Before . WriteLine ( $ "(object) { Context . Parameter . Name } ;") ;
515
- Context . Before . WriteLine ( $ "var { refParamPtr } = &{ castParam } ;") ;
516
- Context . Return . Write ( refParamPtr ) ;
517
- return true ;
518
- }
519
- if ( Context . Function . OperatorKind != CXXOperatorKind . Subscript )
520
- {
521
- if ( Context . Parameter . Kind == ParameterKind . PropertyValue ||
522
- qualifiedPointer . IsConstRefToPrimitive ( ) )
523
- {
524
- Context . Return . Write ( $ "&{ Context . Parameter . Name } ") ;
525
- }
526
- else
527
- {
528
- Context . Before . WriteLine (
529
- $ "fixed ({ realPointer } { refParamPtr } = &{ Context . Parameter . Name } )") ;
530
- Context . HasCodeBlock = true ;
531
- Context . Before . WriteOpenBraceAndIndent ( ) ;
532
- Context . Return . Write ( refParamPtr ) ;
533
- }
534
- return true ;
535
- }
536
- }
537
-
538
497
var param = Context . Parameter ;
539
498
var isRefParam = param != null && ( param . IsInOut || param . IsOut ) ;
540
499
@@ -543,23 +502,69 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
543
502
{
544
503
if ( param . IsOut )
545
504
{
505
+ MarshalString ( pointee ) ;
546
506
Context . Return . Write ( "IntPtr.Zero" ) ;
547
507
Context . ArgumentPrefix . Write ( "&" ) ;
548
508
return true ;
549
509
}
550
- pointer . QualifiedPointee . Visit ( this ) ;
551
510
if ( param . IsInOut )
511
+ {
512
+ MarshalString ( pointee ) ;
513
+ pointer . QualifiedPointee . Visit ( this ) ;
552
514
Context . ArgumentPrefix . Write ( "&" ) ;
515
+ }
553
516
else
554
- Context . Cleanup . WriteLine ( "Marshal.FreeHGlobal({0});" , Context . ArgName ) ;
517
+ {
518
+ pointer . QualifiedPointee . Visit ( this ) ;
519
+ Context . Cleanup . WriteLine ( $ "Marshal.FreeHGlobal({ Context . ArgName } );") ;
520
+ }
555
521
return true ;
556
522
}
557
523
558
- if ( pointee is FunctionType )
559
- return VisitDelegateType ( ) ;
524
+ var finalPointee = ( pointee . GetFinalPointee ( ) ?? pointee ) . Desugar ( ) ;
525
+ if ( finalPointee . IsPrimitiveType ( out PrimitiveType primitive ) ||
526
+ finalPointee . IsEnumType ( ) )
527
+ {
528
+ if ( isRefParam )
529
+ {
530
+ var local = Generator . GeneratedIdentifier ( $@ "{
531
+ param . Name } { Context . ParameterIndex } " ) ;
532
+ Context . Before . WriteLine ( $@ "fixed ({
533
+ pointer . Visit ( typePrinter ) } { local } = &{ param . Name } )" ) ;
534
+ Context . HasCodeBlock = true ;
535
+ Context . Before . WriteOpenBraceAndIndent ( ) ;
536
+ Context . Return . Write ( local ) ;
537
+ return true ;
538
+ }
560
539
561
- Class @class ;
562
- if ( pointee . TryGetClass ( out @class ) && @class . IsValueType )
540
+ if ( Context . Context . Options . MarshalCharAsManagedChar &&
541
+ primitive == PrimitiveType . Char )
542
+ {
543
+ Context . Return . Write ( $ "({ typePrinter . PrintNative ( pointer ) } ) ") ;
544
+ Context . Return . Write ( param . Name ) ;
545
+ return true ;
546
+ }
547
+
548
+ pointer . QualifiedPointee . Visit ( this ) ;
549
+ bool isVoid = primitive == PrimitiveType . Void && pointee . IsAddress ( ) ;
550
+ if ( pointer . Pointee . Desugar ( false ) is TemplateParameterSubstitutionType ||
551
+ isVoid )
552
+ {
553
+ var local = Generator . GeneratedIdentifier ( $@ "{
554
+ param . Name } { Context . ParameterIndex } " ) ;
555
+ string cast = isVoid ? $@ "({ pointee . Visit (
556
+ new CppTypePrinter { PrintTypeQualifiers = false } ) } ) " : string . Empty ;
557
+ Context . Before . WriteLine ( $ "var { local } = { cast } { Context . Return } ;") ;
558
+ Context . Return . StringBuilder . Clear ( ) ;
559
+ Context . Return . Write ( local ) ;
560
+ }
561
+ if ( new QualifiedType ( pointer , quals ) . IsConstRefToPrimitive ( ) )
562
+ Context . Return . StringBuilder . Insert ( 0 , '&' ) ;
563
+
564
+ return true ;
565
+ }
566
+
567
+ if ( pointee . TryGetClass ( out Class @class ) && @class . IsValueType )
563
568
{
564
569
if ( Context . Parameter . Usage == ParameterUsage . Out )
565
570
{
@@ -581,63 +586,13 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
581
586
return true ;
582
587
}
583
588
584
- var finalPointee = pointer . GetFinalPointee ( ) ;
585
- PrimitiveType primitive ;
586
- if ( finalPointee . IsPrimitiveType ( out primitive ) || finalPointee . IsEnumType ( ) )
587
- {
588
- // From MSDN: "note that a ref or out parameter is classified as a moveable
589
- // variable". This means we must create a local variable to hold the result
590
- // and then assign this value to the parameter.
591
-
592
- if ( isRefParam )
593
- {
594
- var typeName = Type . TypePrinterDelegate ( finalPointee ) ;
595
- if ( Context . Function . OperatorKind == CXXOperatorKind . Subscript )
596
- Context . Return . Write ( param . Name ) ;
597
- else
598
- {
599
- if ( param . IsInOut )
600
- Context . Before . WriteLine ( $ "{ typeName } _{ param . Name } = { param . Name } ;") ;
601
- else
602
- Context . Before . WriteLine ( $ "{ typeName } _{ param . Name } ;") ;
603
-
604
- Context . Return . Write ( $ "&_{ param . Name } ") ;
605
- }
606
- }
607
- else
608
- {
609
- if ( Context . Context . Options . MarshalCharAsManagedChar &&
610
- primitive == PrimitiveType . Char )
611
- Context . Return . Write ( $ "({ typePrinter . PrintNative ( pointer ) } ) ") ;
612
-
613
- if ( qualifiedPointer . IsConstRefToPrimitive ( ) )
614
- {
615
- if ( primitive == PrimitiveType . Void && pointee . IsAddress ( ) )
616
- {
617
- string ptr = $@ "{ Helpers . PtrIdentifier } {
618
- Context . ParameterIndex } " ;
619
- Context . Before . WriteLine ( $@ "var { ptr } = {
620
- Context . Parameter . Name } .ToPointer();" ) ;
621
- Context . Return . Write ( $ "&{ ptr } ") ;
622
- return true ;
623
- }
624
- Context . Return . Write ( "&" ) ;
625
- }
626
- Context . Return . Write ( Context . Parameter . Name ) ;
627
- }
628
-
629
- return true ;
630
- }
631
-
632
589
return pointer . QualifiedPointee . Visit ( this ) ;
633
590
}
634
591
635
592
public override bool VisitPrimitiveType ( PrimitiveType primitive , TypeQualifiers quals )
636
593
{
637
594
switch ( primitive )
638
595
{
639
- case PrimitiveType . Void :
640
- return true ;
641
596
case PrimitiveType . Bool :
642
597
if ( Context . MarshalKind == MarshalKind . NativeField )
643
598
{
@@ -657,24 +612,21 @@ public override bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals)
657
612
if ( ! VisitType ( typedef , quals ) )
658
613
return false ;
659
614
660
- var decl = typedef . Declaration ;
661
-
662
- FunctionType func ;
663
- if ( decl . Type . IsPointerTo ( out func ) )
664
- {
665
- VisitDelegateType ( ) ;
666
- return true ;
667
- }
668
-
669
- return decl . Type . Visit ( this ) ;
615
+ return typedef . Declaration . Type . Visit ( this ) ;
670
616
}
671
617
672
618
public override bool VisitTemplateParameterSubstitutionType ( TemplateParameterSubstitutionType param , TypeQualifiers quals )
673
619
{
674
620
var replacement = param . Replacement . Type . Desugar ( ) ;
675
- Class @class ;
676
- if ( ! replacement . IsAddress ( ) && ! replacement . TryGetClass ( out @class ) )
677
- Context . Return . Write ( $ "({ replacement } ) (object) ") ;
621
+ if ( replacement . IsPrimitiveType ( ) ||
622
+ replacement . IsPointerToPrimitiveType ( ) ||
623
+ replacement . IsEnum ( ) )
624
+ {
625
+ Context . Return . Write ( $ "({ replacement } ) ") ;
626
+ if ( replacement . IsPointerToPrimitiveType ( ) )
627
+ Context . Return . Write ( $ "({ CSharpTypePrinter . IntPtrType } ) ") ;
628
+ Context . Return . Write ( "(object) " ) ;
629
+ }
678
630
return base . VisitTemplateParameterSubstitutionType ( param , quals ) ;
679
631
}
680
632
@@ -811,18 +763,18 @@ public override bool VisitClassTemplateDecl(ClassTemplate template)
811
763
return VisitClassDecl ( template . TemplatedClass ) ;
812
764
}
813
765
814
- public override bool VisitFunctionTemplateDecl ( FunctionTemplate template )
815
- {
816
- return template . TemplatedFunction . Visit ( this ) ;
817
- }
818
-
819
- private bool VisitDelegateType ( )
766
+ public override bool VisitFunctionType ( FunctionType function , TypeQualifiers quals )
820
767
{
821
768
Context . Return . Write ( "{0} == null ? global::System.IntPtr.Zero : Marshal.GetFunctionPointerForDelegate({0})" ,
822
769
Context . Parameter . Name ) ;
823
770
return true ;
824
771
}
825
772
773
+ public override bool VisitFunctionTemplateDecl ( FunctionTemplate template )
774
+ {
775
+ return template . TemplatedFunction . Visit ( this ) ;
776
+ }
777
+
826
778
private void ThrowArgumentOutOfRangeException ( )
827
779
{
828
780
Context . Before . WriteLineIndent (
@@ -883,6 +835,17 @@ private void MarshalArray(ArrayType arrayType)
883
835
Context . Return . Write ( intermediateArray ) ;
884
836
}
885
837
838
+ private void MarshalString ( Type pointee )
839
+ {
840
+ var marshal = new CSharpMarshalNativeToManagedPrinter ( Context ) ;
841
+ Context . ReturnVarName = Context . ArgName ;
842
+ Context . ReturnType = Context . Parameter . QualifiedType ;
843
+ pointee . Visit ( marshal ) ;
844
+ Context . Cleanup . WriteLine ( $@ "{ Context . Parameter . Name } = {
845
+ marshal . Context . Return } ;" ) ;
846
+ Context . Return . StringBuilder . Clear ( ) ;
847
+ }
848
+
886
849
private readonly CSharpTypePrinter typePrinter ;
887
850
}
888
851
}
0 commit comments