@@ -106,7 +106,8 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
106106 Helpers . InternalStruct , Context . ReturnVarName ) ;
107107 else
108108 {
109- if ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) &&
109+ if ( ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) ||
110+ arrayType . IsPrimitiveType ( PrimitiveType . WideChar ) ) &&
110111 Context . Context . Options . MarshalCharAsManagedChar )
111112 {
112113 supportBefore . WriteLineIndent (
@@ -130,7 +131,8 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
130131 break ;
131132 case ArrayType . ArraySize . Incomplete :
132133 // 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 ) ) &&
134136 array . QualifiedType . Qualifiers . IsConst )
135137 return VisitPointerType ( new PointerType
136138 {
@@ -155,19 +157,17 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
155157 var isRefParam = param != null && ( param . IsInOut || param . IsOut ) ;
156158
157159 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 ) )
162164 {
163165 Context . Return . Write ( MarshalStringToManaged ( Context . ReturnVarName ,
164166 pointer . GetFinalPointee ( ) . Desugar ( ) as BuiltinType ) ) ;
165167 return true ;
166168 }
167169
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 ( ) )
171171 {
172172 if ( isRefParam )
173173 {
@@ -237,11 +237,13 @@ public override bool VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers
237237 // returned structs must be blittable and char isn't
238238 if ( Context . Context . Options . MarshalCharAsManagedChar )
239239 {
240- Context . Return . Write ( "global::System.Convert.ToChar({0})" ,
241- Context . ReturnVarName ) ;
240+ Context . Return . Write ( $ "global::System.Convert.ToChar({ Context . ReturnVarName } )") ;
242241 return true ;
243242 }
244243 goto default ;
244+ case PrimitiveType . WideChar :
245+ Context . Return . Write ( $ "new CppSharp.Runtime.WideChar({ Context . ReturnVarName } )") ;
246+ return true ;
245247 case PrimitiveType . Char16 :
246248 return false ;
247249 case PrimitiveType . Bool :
@@ -265,16 +267,15 @@ public override bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals)
265267
266268 var decl = typedef . Declaration ;
267269
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 ) )
270271 {
271272 var ptrName = Generator . GeneratedIdentifier ( "ptr" ) +
272273 Context . ParameterIndex ;
273274
274- Context . Before . WriteLine ( "var {0} = {1};" , ptrName ,
275- Context . ReturnVarName ) ;
275+ Context . Before . WriteLine ( $ "var { ptrName } = { Context . ReturnVarName } ;") ;
276276
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 } ))";
278279 Context . Return . Write ( res ) ;
279280 return true ;
280281 }
@@ -286,11 +287,10 @@ public override bool VisitFunctionType(FunctionType function, TypeQualifiers qua
286287 {
287288 var ptrName = Generator . GeneratedIdentifier ( "ptr" ) + Context . ParameterIndex ;
288289
289- Context . Before . WriteLine ( "var {0} = {1};" , ptrName ,
290- Context . ReturnVarName ) ;
290+ Context . Before . WriteLine ( $ "var { ptrName } = { Context . ReturnVarName } ;") ;
291291
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 ( ) } ))" ) ;
294294 return true ;
295295 }
296296
@@ -316,7 +316,7 @@ public override bool VisitClassDecl(Class @class)
316316
317317 public override bool VisitEnumDecl ( Enumeration @enum )
318318 {
319- Context . Return . Write ( "{0}" , Context . ReturnVarName ) ;
319+ Context . Return . Write ( $ " { Context . ReturnVarName } " ) ;
320320 return true ;
321321 }
322322
@@ -340,8 +340,7 @@ public override bool VisitParameterDecl(Parameter parameter)
340340 if ( ! string . IsNullOrWhiteSpace ( ctx . Return ) &&
341341 ! parameter . Type . IsPrimitiveTypeConvertibleToRef ( ) )
342342 {
343- Context . Before . WriteLine ( "var _{0} = {1};" , parameter . Name ,
344- ctx . Return ) ;
343+ Context . Before . WriteLine ( $ "var _{ parameter . Name } = { ctx . Return } ;") ;
345344 }
346345
347346 Context . Return . Write ( "{0}{1}" ,
@@ -512,12 +511,16 @@ public override bool VisitArrayType(ArrayType array, TypeQualifiers quals)
512511 }
513512 else
514513 {
515- if ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) &&
514+ if ( ( arrayType . IsPrimitiveType ( PrimitiveType . Char ) ||
515+ arrayType . IsPrimitiveType ( PrimitiveType . WideChar ) ) &&
516516 Context . Context . Options . MarshalCharAsManagedChar )
517517 {
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]);") ;
521524 }
522525 else
523526 {
@@ -591,6 +594,8 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
591594
592595 var param = Context . Parameter ;
593596 var isRefParam = param != null && ( param . IsInOut || param . IsOut ) ;
597+ var finalPointee = pointer . GetFinalPointee ( ) ;
598+ bool finalPointeeIsPrimitiveType = finalPointee . IsPrimitiveType ( out PrimitiveType primitive ) ;
594599
595600 if ( CSharpTypePrinter . IsConstCharString ( pointee ) && isRefParam )
596601 {
@@ -601,12 +606,12 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
601606 }
602607 else if ( param . IsInOut )
603608 {
604- Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name ) ) ;
609+ Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name , primitive ) ) ;
605610 Context . ArgumentPrefix . Write ( "&" ) ;
606611 }
607612 else
608613 {
609- Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name ) ) ;
614+ Context . Return . Write ( MarshalStringToUnmanaged ( Context . Parameter . Name , primitive ) ) ;
610615 Context . Cleanup . WriteLine ( "Marshal.FreeHGlobal({0});" , Context . ArgName ) ;
611616 }
612617 return true ;
@@ -639,9 +644,7 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
639644 }
640645
641646 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 ( ) ||
645648 marshalAsString )
646649 {
647650 // 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)
667670 {
668671 if ( ! marshalAsString &&
669672 Context . Context . Options . MarshalCharAsManagedChar &&
670- primitive == PrimitiveType . Char )
673+ ( primitive == PrimitiveType . Char || primitive == PrimitiveType . WideChar ) )
671674 Context . Return . Write ( $ "({ typePrinter . PrintNative ( pointer ) } ) ") ;
672675
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 ) ) ;
677678 else
678679 Context . Return . Write ( Context . Parameter . Name ) ;
679680 }
@@ -684,19 +685,25 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
684685 return pointer . QualifiedPointee . Visit ( this ) ;
685686 }
686687
687- private string MarshalStringToUnmanaged ( string varName )
688+ private string MarshalStringToUnmanaged ( string varName , PrimitiveType type )
688689 {
689- if ( Equals ( Context . Context . Options . Encoding , Encoding . ASCII ) )
690+ if ( type == PrimitiveType . WideChar )
690691 {
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 } )";
692695 }
696+
697+ if ( Equals ( Context . Context . Options . Encoding , Encoding . ASCII ) )
698+ return $ "Marshal.StringToHGlobalAnsi({ varName } )";
699+
693700 if ( Equals ( Context . Context . Options . Encoding , Encoding . Unicode ) ||
694701 Equals ( Context . Context . Options . Encoding , Encoding . BigEndianUnicode ) )
695702 {
696- return string . Format ( "Marshal.StringToHGlobalUni({0 })" , varName ) ;
703+ return $ "Marshal.StringToHGlobalUni({ varName } )";
697704 }
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." ) ;
700707 }
701708
702709 public override bool VisitPrimitiveType ( PrimitiveType primitive , TypeQualifiers quals )
@@ -714,6 +721,15 @@ public override bool VisitPrimitiveType(PrimitiveType primitive, TypeQualifiers
714721 return true ;
715722 }
716723 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 ;
717733 case PrimitiveType . Char16 :
718734 return false ;
719735 case PrimitiveType . Bool :
0 commit comments