@ -129,7 +129,7 @@ namespace CppSharp.Types.Std
encoding = Context . Options . Encoding ;
encoding = Context . Options . Encoding ;
string param ;
string param ;
if ( Equals ( encoding , Encoding . ASCII ) )
if ( Equals ( encoding , Encoding . ASCII ) | | Equals ( encoding , Encoding . UTF8 ) )
param = "E_UTF8" ;
param = "E_UTF8" ;
else if ( Equals ( encoding , Encoding . Unicode ) | |
else if ( Equals ( encoding , Encoding . Unicode ) | |
Equals ( encoding , Encoding . BigEndianUnicode ) )
Equals ( encoding , Encoding . BigEndianUnicode ) )
@ -154,8 +154,9 @@ namespace CppSharp.Types.Std
return new CustomType ( typePrinter . IntPtrType ) ;
return new CustomType ( typePrinter . IntPtrType ) ;
}
}
if ( Context . Options . Encoding = = Encoding . ASCII )
if ( Context . Options . Encoding = = Encoding . ASCII | |
return new CustomType ( "string" ) ;
Context . Options . Encoding = = Encoding . UTF8 )
return new CustomType ( "[MarshalAs(UnmanagedType.LPUTF8Str)] string" ) ;
if ( Context . Options . Encoding = = Encoding . Unicode | |
if ( Context . Options . Encoding = = Encoding . Unicode | |
Context . Options . Encoding = = Encoding . BigEndianUnicode )
Context . Options . Encoding = = Encoding . BigEndianUnicode )
@ -183,19 +184,14 @@ namespace CppSharp.Types.Std
if ( substitution ! = null )
if ( substitution ! = null )
param = $"({substitution.Replacement}) (object) {param}" ;
param = $"({substitution.Replacement}) (object) {param}" ;
if ( Equals ( Context . Options . Encoding , Encoding . ASCII ) )
string bytes = $"__bytes{ctx.ParameterIndex}" ;
{
string bytePtr = $"__bytePtr{ctx.ParameterIndex}" ;
ctx . Return . Write ( $"Marshal.StringToHGlobalAnsi({param})" ) ;
ctx . Before . WriteLine ( $ @ "byte[] {bytes} = global::System.Text.Encoding.{
return ;
GetEncodingClass ( ctx . Parameter ) } . GetBytes ( { param } ) ; ");
}
ctx . Before . WriteLine ( $"fixed (byte* {bytePtr} = {bytes})" ) ;
if ( Equals ( Context . Options . Encoding , Encoding . Unicode ) | |
ctx . HasCodeBlock = true ;
Equals ( Context . Options . Encoding , Encoding . BigEndianUnicode ) )
ctx . Before . WriteOpenBraceAndIndent ( ) ;
{
ctx . Return . Write ( $"new global::System.IntPtr({bytePtr})" ) ;
ctx . Return . Write ( $"Marshal.StringToHGlobalUni({param})" ) ;
return ;
}
throw new System . NotSupportedException (
$"{Context.Options.Encoding.EncodingName} is not supported yet." ) ;
}
}
public override void CSharpMarshalToManaged ( CSharpMarshalContext ctx )
public override void CSharpMarshalToManaged ( CSharpMarshalContext ctx )
@ -207,49 +203,93 @@ namespace CppSharp.Types.Std
return ;
return ;
}
}
Type type = Type . Desugar ( ) ;
Type pointee = type . GetPointee ( ) . Desugar ( ) ;
var isChar = type . IsPointerToPrimitiveType ( PrimitiveType . Char ) | |
( pointee . IsPointerToPrimitiveType ( PrimitiveType . Char ) & &
ctx . Parameter ! = null & &
( ctx . Parameter . IsInOut | | ctx . Parameter . IsOut ) ) ;
var encoding = isChar ? Encoding . ASCII : Encoding . Unicode ;
if ( Equals ( encoding , Encoding . ASCII ) )
encoding = Context . Options . Encoding ;
string returnVarName = ctx . ReturnVarName ;
string returnVarName = ctx . ReturnVarName ;
string nullPtr = "global::System.IntPtr.Zero" ;
if ( ctx . Function ! = null )
if ( ctx . Function ! = null )
{
{
Type returnType = ctx . Function . ReturnType . Type . Desugar ( ) ;
Type returnType = ctx . Function . ReturnType . Type . Desugar ( ) ;
if ( returnType . IsAddress ( ) & &
if ( returnType . IsAddress ( ) & &
returnType . GetPointee ( ) . Desugar ( ) . IsAddress ( ) )
returnType . GetPointee ( ) . Desugar ( ) . IsAddress ( ) )
{
{
returnVarName = $"new global::System.IntPtr(*{returnVarName})" ;
returnVarName = $"*{returnVarName}" ;
nullPtr = "null" ;
}
}
}
}
if ( Equals ( encoding , Encoding . ASCII ) )
TextGenerator textGenerator ;
if ( ctx . Parameter = = null )
{
{
ctx . Return . Write ( $"Marshal.PtrToStringAnsi({returnVarName})" ) ;
textGenerator = ctx . Before ;
return ;
textGenerator . WriteLine ( $"if ({ctx.ReturnVarName} == {nullPtr})" ) ;
textGenerator . WriteLineIndent ( $"return default({ctx.ReturnType});" ) ;
}
}
if ( Equals ( encoding , Encoding . UTF8 ) )
else
{
{
ctx . Return . Write ( $"Marshal.PtrToStringUTF8({returnVarName})" ) ;
textGenerator = ctx . Cleanup ;
return ;
textGenerator . WriteLine ( $"if ({ctx.ReturnVarName} == {nullPtr})" ) ;
textGenerator . WriteOpenBraceAndIndent ( ) ;
textGenerator . WriteLine ( $"{ctx.Parameter.Name} = default({Type.Desugar()});" ) ;
textGenerator . WriteLine ( "return;" ) ;
textGenerator . UnindentAndWriteCloseBrace ( ) ;
}
}
// If we reach this, we know the string is Unicode.
string encoding = GetEncodingClass ( ctx . Parameter ) ;
if ( isChar | | ctx . Context . TargetInfo . WCharWidth = = 1 6 )
string type = GetTypeForCodePoint ( encoding ) ;
textGenerator . WriteLine ( $"var __retPtr = ({type}*) {returnVarName};" ) ;
textGenerator . WriteLine ( "int __length = 0;" ) ;
textGenerator . WriteLine ( $"while (*(__retPtr++) != 0) __length += sizeof({type});" ) ;
ctx . Return . Write ( $ @ "global::System.Text.Encoding.{
encoding } . GetString ( ( byte * ) { returnVarName } , _ _l ength ) ");
}
private string GetEncodingClass ( Parameter parameter )
{
Type type = Type . Desugar ( ) ;
Type pointee = type . GetPointee ( ) . Desugar ( ) ;
var isChar = type . IsPointerToPrimitiveType ( PrimitiveType . Char ) | |
( pointee . IsPointerToPrimitiveType ( PrimitiveType . Char ) & &
parameter ! = null & &
( parameter . IsInOut | | parameter . IsOut ) ) ;
if ( ! isChar )
return ( Context . TargetInfo . WCharWidth = = 1 6 ) ?
nameof ( Encoding . Unicode ) : nameof ( Encoding . UTF32 ) ;
if ( Context . Options . Encoding = = Encoding . ASCII )
return nameof ( Encoding . ASCII ) ;
if ( Context . Options . Encoding = = Encoding . BigEndianUnicode )
return nameof ( Encoding . BigEndianUnicode ) ;
if ( Context . Options . Encoding = = Encoding . Unicode )
return nameof ( Encoding . Unicode ) ;
if ( Context . Options . Encoding = = Encoding . UTF32 )
return nameof ( Encoding . UTF32 ) ;
if ( Context . Options . Encoding = = Encoding . UTF7 )
return nameof ( Encoding . UTF7 ) ;
if ( Context . Options . Encoding = = Encoding . UTF8 )
return nameof ( Encoding . UTF8 ) ;
throw new System . NotSupportedException (
$"{Context.Options.Encoding.EncodingName} is not supported yet." ) ;
}
private static string GetTypeForCodePoint ( string encoding )
{
switch ( encoding )
{
{
ctx . Return . Write ( $"Marshal.PtrToStringUni({returnVarName})" ) ;
case nameof ( Encoding . UTF32 ) :
return ;
return "int" ;
case nameof ( Encoding . Unicode ) :
case nameof ( Encoding . BigEndianUnicode ) :
return "short" ;
default :
return "byte" ;
}
}
// If we reach this, we should have an UTF-32 wide string.
const string encodingName = "System.Text.Encoding.UTF32" ;
ctx . Return . Write ( $ @ "CppSharp.Runtime.Helpers.MarshalEncodedString({
returnVarName } , { encodingName } ) ");
}
}
}
}