@@ -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,17 +157,16 @@ 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
170
PrimitiveType primitive ;
170
171
if ( finalPointee . IsPrimitiveType ( out primitive ) || finalPointee . IsEnumType ( ) )
171
172
{
@@ -237,11 +238,13 @@ public override bool VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers
237
238
// returned structs must be blittable and char isn't
238
239
if ( Context . Context . Options . MarshalCharAsManagedChar )
239
240
{
240
- Context . Return . Write ( "global::System.Convert.ToChar({0})" ,
241
- Context . ReturnVarName ) ;
241
+ Context . Return . Write ( $ "global::System.Convert.ToChar({ Context . ReturnVarName } )") ;
242
242
return true ;
243
243
}
244
244
goto default ;
245
+ case PrimitiveType . WideChar :
246
+ Context . Return . Write ( $ "new CppSharp.Runtime.WideChar({ Context . ReturnVarName } )") ;
247
+ return true ;
245
248
case PrimitiveType . Char16 :
246
249
return false ;
247
250
case PrimitiveType . Bool :
@@ -271,10 +274,10 @@ public override bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals)
271
274
var ptrName = Generator . GeneratedIdentifier ( "ptr" ) +
272
275
Context . ParameterIndex ;
273
276
274
- Context . Before . WriteLine ( "var {0} = {1};" , ptrName ,
275
- Context . ReturnVarName ) ;
277
+ Context . Before . WriteLine ( $ "var { ptrName } = { Context . ReturnVarName } ;") ;
276
278
277
- var res = $ "{ ptrName } == IntPtr.Zero? null : ({ typedef } )Marshal.GetDelegateForFunctionPointer({ ptrName } , typeof({ typedef } ))";
279
+ var res = $@ "{ ptrName } == IntPtr.Zero? null : ({ typedef
280
+ } )Marshal.GetDelegateForFunctionPointer({ ptrName } , typeof({ typedef } ))";
278
281
Context . Return . Write ( res ) ;
279
282
return true ;
280
283
}
@@ -286,11 +289,10 @@ public override bool VisitFunctionType(FunctionType function, TypeQualifiers qua
286
289
{
287
290
var ptrName = Generator . GeneratedIdentifier ( "ptr" ) + Context . ParameterIndex ;
288
291
289
- Context . Before . WriteLine ( "var {0} = {1};" , ptrName ,
290
- Context . ReturnVarName ) ;
292
+ Context . Before . WriteLine ( $ "var { ptrName } = { Context . ReturnVarName } ;") ;
291
293
292
- Context . Return . Write ( "({1})Marshal.GetDelegateForFunctionPointer({0}, typeof({1}))" ,
293
- ptrName , function . ToString ( ) ) ;
294
+ Context . Return . Write ( $@ "({ function . ToString ( )
295
+ } )Marshal.GetDelegateForFunctionPointer( { ptrName } , typeof( { function . ToString ( ) } ))" ) ;
294
296
return true ;
295
297
}
296
298
@@ -316,7 +318,7 @@ public override bool VisitClassDecl(Class @class)
316
318
317
319
public override bool VisitEnumDecl ( Enumeration @enum )
318
320
{
319
- Context . Return . Write ( "{0}" , Context . ReturnVarName ) ;
321
+ Context . Return . Write ( $ " { Context . ReturnVarName } " ) ;
320
322
return true ;
321
323
}
322
324
@@ -340,8 +342,7 @@ public override bool VisitParameterDecl(Parameter parameter)
340
342
if ( ! string . IsNullOrWhiteSpace ( ctx . Return ) &&
341
343
! parameter . Type . IsPrimitiveTypeConvertibleToRef ( ) )
342
344
{
343
- Context . Before . WriteLine ( "var _{0} = {1};" , parameter . Name ,
344
- ctx . Return ) ;
345
+ Context . Before . WriteLine ( $ "var _{ parameter . Name } = { ctx . Return } ;") ;
345
346
}
346
347
347
348
Context . Return . Write ( "{0}{1}" ,
@@ -512,12 +513,16 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
512
513
}
513
514
else
514
515
{
515
- if ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) &&
516
+ if ( ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) ||
517
+ arrayType . IsPrimitiveType ( PrimitiveType . WideChar ) ) &&
516
518
Context . Context . Options . MarshalCharAsManagedChar )
517
519
{
518
- supportBefore . WriteLineIndent (
519
- "{0}[i] = global::System.Convert.ToSByte({1}[i]);" ,
520
- Context . ReturnVarName , Context . ArgName ) ;
520
+ if ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) )
521
+ supportBefore . WriteLineIndent (
522
+ $ "{ Context . ReturnVarName } [i] = global::System.Convert.ToSByte({ Context . ArgName } [i]);") ;
523
+ else
524
+ supportBefore . WriteLineIndent (
525
+ $ "{ Context . ReturnVarName } [i] = global::System.Convert.ToChar({ Context . ArgName } [i]);") ;
521
526
}
522
527
else
523
528
{
@@ -591,6 +596,10 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
591
596
592
597
var param = Context . Parameter ;
593
598
var isRefParam = param != null && ( param . IsInOut || param . IsOut ) ;
599
+ var finalPointee = pointer . GetFinalPointee ( ) ;
600
+
601
+ PrimitiveType primitive ;
602
+ bool finalPointeeIsPrimitiveType = finalPointee . IsPrimitiveType ( out primitive ) ;
594
603
595
604
if ( CSharpTypePrinter . IsConstCharString ( pointee ) && isRefParam )
596
605
{
@@ -601,12 +610,12 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
601
610
}
602
611
else if ( param . IsInOut )
603
612
{
604
- Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name ) ) ;
613
+ Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name , primitive ) ) ;
605
614
Context . ArgumentPrefix . Write ( "&" ) ;
606
615
}
607
616
else
608
617
{
609
- Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name ) ) ;
618
+ Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name , primitive ) ) ;
610
619
Context . Cleanup . WriteLine ( "Marshal.FreeHGlobal({0});" , Context . ArgName ) ;
611
620
}
612
621
return true ;
@@ -639,9 +648,7 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
639
648
}
640
649
641
650
var marshalAsString = CSharpTypePrinter . IsConstCharString ( pointer ) ;
642
- var finalPointee = pointer . GetFinalPointee ( ) ;
643
- PrimitiveType primitive ;
644
- if ( finalPointee . IsPrimitiveType ( out primitive ) || finalPointee . IsEnumType ( ) ||
651
+ if ( finalPointeeIsPrimitiveType || finalPointee . IsEnumType ( ) ||
645
652
marshalAsString )
646
653
{
647
654
// From MSDN: "note that a ref or out parameter is classified as a moveable
@@ -667,13 +674,11 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
667
674
{
668
675
if ( ! marshalAsString &&
669
676
Context . Context . Options . MarshalCharAsManagedChar &&
670
- primitive == PrimitiveType . Char )
677
+ ( primitive == PrimitiveType . Char || primitive == PrimitiveType . WideChar ) )
671
678
Context . Return . Write ( $ "({ typePrinter . PrintNative ( pointer ) } ) ") ;
672
679
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 ) ) ;
680
+ if ( marshalAsString )
681
+ Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name , primitive ) ) ;
677
682
else
678
683
Context . Return . Write ( Context . Parameter . Name ) ;
679
684
}
@@ -684,19 +689,25 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
684
689
return pointer . QualifiedPointee . Visit ( this ) ;
685
690
}
686
691
687
- private string MarshalStringToUnmanaged ( string varName )
692
+ private string MarshalStringToUnmanaged ( string varName , PrimitiveType type )
688
693
{
689
- if ( Equals ( Context . Context . Options . Encoding , Encoding . ASCII ) )
694
+ if ( type == PrimitiveType . WideChar )
690
695
{
691
- return string . Format ( "Marshal.StringToHGlobalAnsi({0})" , varName ) ;
696
+ // Looks like Marshal.StringToHGlobalUni is already able
697
+ // to handle both Unicode and MBCS charsets
698
+ return $ "Marshal.StringToHGlobalUni({ varName } )";
692
699
}
700
+
701
+ if ( Equals ( Context . Context . Options . Encoding , Encoding . ASCII ) )
702
+ return $ "Marshal.StringToHGlobalAnsi({ varName } )";
703
+
693
704
if ( Equals ( Context . Context . Options . Encoding , Encoding . Unicode ) ||
694
705
Equals ( Context . Context . Options . Encoding , Encoding . BigEndianUnicode ) )
695
706
{
696
- return string . Format ( "Marshal.StringToHGlobalUni({0 })" , varName ) ;
707
+ return $ "Marshal.StringToHGlobalUni({ varName } )";
697
708
}
698
- throw new NotSupportedException ( string . Format ( "{0} is not supported yet." ,
699
- Context . Context . Options . Encoding . EncodingName ) ) ;
709
+ throw new NotSupportedException (
710
+ $ " { Context . Context . Options . Encoding . EncodingName } is not supported yet." ) ;
700
711
}
701
712
702
713
public override bool VisitPrimitiveType ( PrimitiveType primitive , TypeQualifiers quals )
@@ -714,6 +725,15 @@ public override bool VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers
714
725
return true ;
715
726
}
716
727
goto default ;
728
+ case PrimitiveType . WideChar :
729
+ // returned structs must be blittable and char isn't
730
+ if ( Context . Context . Options . MarshalCharAsManagedChar )
731
+ {
732
+ Context . Return . Write ( "global::System.Convert.ToChar({0})" ,
733
+ Context . Parameter . Name ) ;
734
+ return true ;
735
+ }
736
+ goto default ;
717
737
case PrimitiveType . Char16 :
718
738
return false ;
719
739
case PrimitiveType . Bool :
0 commit comments