@@ -106,7 +106,8 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
106
106
Helpers . InternalStruct , Context . ReturnVarName ) ;
107
107
else
108
108
{
109
- if ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) &&
109
+ if ( ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) ||
110
+ arrayType . IsPrimitiveType ( PrimitiveType . WideChar ) ) &&
110
111
Context . Context . Options . MarshalCharAsManagedChar )
111
112
{
112
113
supportBefore . WriteLineIndent (
@@ -130,7 +131,8 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
130
131
break ;
131
132
case ArrayType . ArraySize . Incomplete :
132
133
// const char* and const char[] are the same so we can use a string
133
- if ( array . Type . Desugar ( ) . IsPrimitiveType ( PrimitiveType . Char ) &&
134
+ if ( ( array . Type . Desugar ( ) . IsPrimitiveType ( PrimitiveType . Char ) ||
135
+ array . Type . Desugar ( ) . IsPrimitiveType ( PrimitiveType . WideChar ) ) &&
134
136
array . QualifiedType . Qualifiers . IsConst )
135
137
return VisitPointerType ( new PointerType
136
138
{
@@ -155,19 +157,17 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
155
157
var isRefParam = param != null && ( param . IsInOut || param . IsOut ) ;
156
158
157
159
var pointee = pointer . Pointee . Desugar ( ) ;
158
- bool marshalPointeeAsString = CSharpTypePrinter . IsConstCharString ( pointee ) && isRefParam ;
159
-
160
- if ( ( CSharpTypePrinter . IsConstCharString ( pointer ) && ! MarshalsParameter ) ||
161
- marshalPointeeAsString )
160
+ var finalPointee = pointer . GetFinalPointee ( ) ;
161
+
162
+ if ( CSharpTypePrinter . IsConstCharString ( pointer ) ||
163
+ ( CSharpTypePrinter . IsConstCharString ( pointee ) && isRefParam ) )
162
164
{
163
165
Context . Return . Write ( MarshalStringToManaged ( Context . ReturnVarName ,
164
166
pointer . GetFinalPointee ( ) . Desugar ( ) as BuiltinType ) ) ;
165
167
return true ;
166
168
}
167
169
168
- var finalPointee = pointer . GetFinalPointee ( ) ;
169
- PrimitiveType primitive ;
170
- if ( finalPointee . IsPrimitiveType ( out primitive ) || finalPointee . IsEnumType ( ) )
170
+ if ( finalPointee . IsPrimitiveType ( out PrimitiveType primitive ) || finalPointee . IsEnumType ( ) )
171
171
{
172
172
if ( isRefParam )
173
173
{
@@ -237,11 +237,13 @@ public override bool VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers
237
237
// returned structs must be blittable and char isn't
238
238
if ( Context . Context . Options . MarshalCharAsManagedChar )
239
239
{
240
- Context . Return . Write ( "global::System.Convert.ToChar({0})" ,
241
- Context . ReturnVarName ) ;
240
+ Context . Return . Write ( $ "global::System.Convert.ToChar({ Context . ReturnVarName } )") ;
242
241
return true ;
243
242
}
244
243
goto default ;
244
+ case PrimitiveType . WideChar :
245
+ Context . Return . Write ( $ "new CppSharp.Runtime.WideChar({ Context . ReturnVarName } )") ;
246
+ return true ;
245
247
case PrimitiveType . Char16 :
246
248
return false ;
247
249
case PrimitiveType . Bool :
@@ -265,16 +267,15 @@ public override bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals)
265
267
266
268
var decl = typedef . Declaration ;
267
269
268
- var functionType = decl . Type as FunctionType ;
269
- if ( functionType != null || decl . Type . IsPointerTo ( out functionType ) )
270
+ if ( decl . Type is FunctionType functionType || decl . Type . IsPointerTo ( out functionType ) )
270
271
{
271
272
var ptrName = Generator . GeneratedIdentifier ( "ptr" ) +
272
273
Context . ParameterIndex ;
273
274
274
- Context . Before . WriteLine ( "var {0} = {1};" , ptrName ,
275
- Context . ReturnVarName ) ;
275
+ Context . Before . WriteLine ( $ "var { ptrName } = { Context . ReturnVarName } ;") ;
276
276
277
- var res = $ "{ ptrName } == IntPtr.Zero? null : ({ typedef } )Marshal.GetDelegateForFunctionPointer({ ptrName } , typeof({ typedef } ))";
277
+ var res = $@ "{ ptrName } == IntPtr.Zero? null : ({ typedef
278
+ } )Marshal.GetDelegateForFunctionPointer({ ptrName } , typeof({ typedef } ))";
278
279
Context . Return . Write ( res ) ;
279
280
return true ;
280
281
}
@@ -286,11 +287,10 @@ public override bool VisitFunctionType(FunctionType function, TypeQualifiers qua
286
287
{
287
288
var ptrName = Generator . GeneratedIdentifier ( "ptr" ) + Context . ParameterIndex ;
288
289
289
- Context . Before . WriteLine ( "var {0} = {1};" , ptrName ,
290
- Context . ReturnVarName ) ;
290
+ Context . Before . WriteLine ( $ "var { ptrName } = { Context . ReturnVarName } ;") ;
291
291
292
- Context . Return . Write ( "({1})Marshal.GetDelegateForFunctionPointer({0}, typeof({1}))" ,
293
- ptrName , function . ToString ( ) ) ;
292
+ Context . Return . Write ( $@ "({ function . ToString ( )
293
+ } )Marshal.GetDelegateForFunctionPointer( { ptrName } , typeof( { function . ToString ( ) } ))" ) ;
294
294
return true ;
295
295
}
296
296
@@ -316,7 +316,7 @@ public override bool VisitClassDecl(Class @class)
316
316
317
317
public override bool VisitEnumDecl ( Enumeration @enum )
318
318
{
319
- Context . Return . Write ( "{0}" , Context . ReturnVarName ) ;
319
+ Context . Return . Write ( $ " { Context . ReturnVarName } " ) ;
320
320
return true ;
321
321
}
322
322
@@ -340,8 +340,7 @@ public override bool VisitParameterDecl(Parameter parameter)
340
340
if ( ! string . IsNullOrWhiteSpace ( ctx . Return ) &&
341
341
! parameter . Type . IsPrimitiveTypeConvertibleToRef ( ) )
342
342
{
343
- Context . Before . WriteLine ( "var _{0} = {1};" , parameter . Name ,
344
- ctx . Return ) ;
343
+ Context . Before . WriteLine ( $ "var _{ parameter . Name } = { ctx . Return } ;") ;
345
344
}
346
345
347
346
Context . Return . Write ( "{0}{1}" ,
@@ -512,12 +511,16 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
512
511
}
513
512
else
514
513
{
515
- if ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) &&
514
+ if ( ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) ||
515
+ arrayType . IsPrimitiveType ( PrimitiveType . WideChar ) ) &&
516
516
Context . Context . Options . MarshalCharAsManagedChar )
517
517
{
518
- supportBefore . WriteLineIndent (
519
- "{0}[i] = global::System.Convert.ToSByte({1}[i]);" ,
520
- Context . ReturnVarName , Context . ArgName ) ;
518
+ if ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) )
519
+ supportBefore . WriteLineIndent (
520
+ $ "{ Context . ReturnVarName } [i] = global::System.Convert.ToSByte({ Context . ArgName } [i]);") ;
521
+ else
522
+ supportBefore . WriteLineIndent (
523
+ $ "{ Context . ReturnVarName } [i] = global::System.Convert.ToChar({ Context . ArgName } [i]);") ;
521
524
}
522
525
else
523
526
{
@@ -591,6 +594,8 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
591
594
592
595
var param = Context . Parameter ;
593
596
var isRefParam = param != null && ( param . IsInOut || param . IsOut ) ;
597
+ var finalPointee = pointer . GetFinalPointee ( ) ;
598
+ bool finalPointeeIsPrimitiveType = finalPointee . IsPrimitiveType ( out PrimitiveType primitive ) ;
594
599
595
600
if ( CSharpTypePrinter . IsConstCharString ( pointee ) && isRefParam )
596
601
{
@@ -601,12 +606,12 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
601
606
}
602
607
else if ( param . IsInOut )
603
608
{
604
- Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name ) ) ;
609
+ Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name , primitive ) ) ;
605
610
Context . ArgumentPrefix . Write ( "&" ) ;
606
611
}
607
612
else
608
613
{
609
- Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name ) ) ;
614
+ Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name , primitive ) ) ;
610
615
Context . Cleanup . WriteLine ( "Marshal.FreeHGlobal({0});" , Context . ArgName ) ;
611
616
}
612
617
return true ;
@@ -639,9 +644,7 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
639
644
}
640
645
641
646
var marshalAsString = CSharpTypePrinter . IsConstCharString ( pointer ) ;
642
- var finalPointee = pointer . GetFinalPointee ( ) ;
643
- PrimitiveType primitive ;
644
- if ( finalPointee . IsPrimitiveType ( out primitive ) || finalPointee . IsEnumType ( ) ||
647
+ if ( finalPointeeIsPrimitiveType || finalPointee . IsEnumType ( ) ||
645
648
marshalAsString )
646
649
{
647
650
// From MSDN: "note that a ref or out parameter is classified as a moveable
@@ -667,13 +670,11 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
667
670
{
668
671
if ( ! marshalAsString &&
669
672
Context . Context . Options . MarshalCharAsManagedChar &&
670
- primitive == PrimitiveType . Char )
673
+ ( primitive == PrimitiveType . Char || primitive == PrimitiveType . WideChar ) )
671
674
Context . Return . Write ( $ "({ typePrinter . PrintNative ( pointer ) } ) ") ;
672
675
673
- if ( marshalAsString && ( Context . MarshalKind == MarshalKind . NativeField ||
674
- Context . MarshalKind == MarshalKind . VTableReturnValue ||
675
- Context . MarshalKind == MarshalKind . Variable ) )
676
- Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name ) ) ;
676
+ if ( marshalAsString )
677
+ Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name , primitive ) ) ;
677
678
else
678
679
Context . Return . Write ( Context . Parameter . Name ) ;
679
680
}
@@ -684,19 +685,25 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
684
685
return pointer . QualifiedPointee . Visit ( this ) ;
685
686
}
686
687
687
- private string MarshalStringToUnmanaged ( string varName )
688
+ private string MarshalStringToUnmanaged ( string varName , PrimitiveType type )
688
689
{
689
- if ( Equals ( Context . Context . Options . Encoding , Encoding . ASCII ) )
690
+ if ( type == PrimitiveType . WideChar )
690
691
{
691
- return string . Format ( "Marshal.StringToHGlobalAnsi({0})" , varName ) ;
692
+ // Looks like Marshal.StringToHGlobalUni is already able
693
+ // to handle both Unicode and MBCS charsets
694
+ return $ "Marshal.StringToHGlobalUni({ varName } )";
692
695
}
696
+
697
+ if ( Equals ( Context . Context . Options . Encoding , Encoding . ASCII ) )
698
+ return $ "Marshal.StringToHGlobalAnsi({ varName } )";
699
+
693
700
if ( Equals ( Context . Context . Options . Encoding , Encoding . Unicode ) ||
694
701
Equals ( Context . Context . Options . Encoding , Encoding . BigEndianUnicode ) )
695
702
{
696
- return string . Format ( "Marshal.StringToHGlobalUni({0 })" , varName ) ;
703
+ return $ "Marshal.StringToHGlobalUni({ varName } )";
697
704
}
698
- throw new NotSupportedException ( string . Format ( "{0} is not supported yet." ,
699
- Context . Context . Options . Encoding . EncodingName ) ) ;
705
+ throw new NotSupportedException (
706
+ $ " { Context . Context . Options . Encoding . EncodingName } is not supported yet." ) ;
700
707
}
701
708
702
709
public override bool VisitPrimitiveType ( PrimitiveType primitive , TypeQualifiers quals )
@@ -714,6 +721,15 @@ public override bool VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers
714
721
return true ;
715
722
}
716
723
goto default ;
724
+ case PrimitiveType . WideChar :
725
+ // returned structs must be blittable and char isn't
726
+ if ( Context . Context . Options . MarshalCharAsManagedChar )
727
+ {
728
+ Context . Return . Write ( "global::System.Convert.ToChar({0})" ,
729
+ Context . Parameter . Name ) ;
730
+ return true ;
731
+ }
732
+ goto default ;
717
733
case PrimitiveType . Char16 :
718
734
return false ;
719
735
case PrimitiveType . Bool :
0 commit comments