|  | 
|  | 1 | +using System.Text; | 
|  | 2 | +using CppSharp.AST; | 
|  | 3 | +using CppSharp.AST.Extensions; | 
|  | 4 | +using CppSharp.Generators; | 
|  | 5 | +using CppSharp.Generators.AST; | 
|  | 6 | +using CppSharp.Generators.C; | 
|  | 7 | +using CppSharp.Generators.CLI; | 
|  | 8 | +using CppSharp.Generators.CSharp; | 
|  | 9 | + | 
|  | 10 | +namespace CppSharp.Types.Std | 
|  | 11 | +{ | 
|  | 12 | +    [TypeMap("const char*", GeneratorKind = GeneratorKind.CLI)] | 
|  | 13 | +    public partial class ConstCharPointer : TypeMap | 
|  | 14 | +    { | 
|  | 15 | +        public override Type CLISignatureType(TypePrinterContext ctx) | 
|  | 16 | +        { | 
|  | 17 | +            return new CILType(typeof(string)); | 
|  | 18 | +        } | 
|  | 19 | + | 
|  | 20 | +        public override void CLIMarshalToNative(MarshalContext ctx) | 
|  | 21 | +        { | 
|  | 22 | +            ctx.Before.WriteLine( | 
|  | 23 | +                "auto _{0} = clix::marshalString<clix::E_UTF8>({1});", | 
|  | 24 | +                ctx.ArgName, ctx.Parameter.Name); | 
|  | 25 | + | 
|  | 26 | +            ctx.Return.Write("_{0}.c_str()", ctx.ArgName); | 
|  | 27 | +        } | 
|  | 28 | + | 
|  | 29 | +        public override void CLIMarshalToManaged(MarshalContext ctx) | 
|  | 30 | +        { | 
|  | 31 | +            if (ctx.Parameter != null && !ctx.Parameter.IsOut && | 
|  | 32 | +                !ctx.Parameter.IsInOut) | 
|  | 33 | +            { | 
|  | 34 | +                ctx.Return.Write(ctx.Parameter.Name); | 
|  | 35 | +                return; | 
|  | 36 | +            } | 
|  | 37 | + | 
|  | 38 | +            Type type = ctx.ReturnType.Type.Desugar(); | 
|  | 39 | +            Type pointee = type.GetPointee().Desugar(); | 
|  | 40 | +            var isChar = type.IsPointerToPrimitiveType(PrimitiveType.Char) || | 
|  | 41 | +                (pointee.IsPointerToPrimitiveType(PrimitiveType.Char) && | 
|  | 42 | +                 ctx.Parameter != null && | 
|  | 43 | +                 (ctx.Parameter.IsInOut || ctx.Parameter.IsOut)); | 
|  | 44 | +            var encoding = isChar ? Encoding.ASCII : Encoding.Unicode; | 
|  | 45 | + | 
|  | 46 | +            if (Equals(encoding, Encoding.ASCII)) | 
|  | 47 | +                encoding = Context.Options.Encoding; | 
|  | 48 | + | 
|  | 49 | +            string param; | 
|  | 50 | +            if (Equals(encoding, Encoding.ASCII) || Equals(encoding, Encoding.UTF8)) | 
|  | 51 | +                param = "E_UTF8"; | 
|  | 52 | +            else if (Equals(encoding, Encoding.Unicode) || | 
|  | 53 | +                     Equals(encoding, Encoding.BigEndianUnicode)) | 
|  | 54 | +                param = "E_UTF16"; | 
|  | 55 | +            else | 
|  | 56 | +                throw new System.NotSupportedException( | 
|  | 57 | +                    $"{Context.Options.Encoding.EncodingName} is not supported yet."); | 
|  | 58 | + | 
|  | 59 | +            ctx.Return.Write( | 
|  | 60 | +                $@"({ctx.ReturnVarName} == 0 ? nullptr : clix::marshalString<clix::{ | 
|  | 61 | +                    param}>({ctx.ReturnVarName}))"); | 
|  | 62 | +        } | 
|  | 63 | +    } | 
|  | 64 | + | 
|  | 65 | +    [TypeMap("const char[]", GeneratorKind = GeneratorKind.CLI)] | 
|  | 66 | +    public partial class ConstCharArray : ConstCharPointer | 
|  | 67 | +    { | 
|  | 68 | +    } | 
|  | 69 | + | 
|  | 70 | +    [TypeMap("const wchar_t*", GeneratorKind = GeneratorKind.CLI)] | 
|  | 71 | +    public partial class ConstWCharTPointer : ConstCharPointer | 
|  | 72 | +    { | 
|  | 73 | +    } | 
|  | 74 | + | 
|  | 75 | +    [TypeMap("const char16_t*", GeneratorKind = GeneratorKind.CLI)] | 
|  | 76 | +    public partial class ConstChar16TPointer : ConstCharPointer | 
|  | 77 | +    { | 
|  | 78 | +    } | 
|  | 79 | + | 
|  | 80 | +    [TypeMap("const char32_t*", GeneratorKind = GeneratorKind.CLI)] | 
|  | 81 | +    public partial class ConstChar32TPointer : ConstCharPointer | 
|  | 82 | +    { | 
|  | 83 | +    } | 
|  | 84 | + | 
|  | 85 | +    [TypeMap("basic_string<char, char_traits<char>, allocator<char>>", GeneratorKind = GeneratorKind.CLI)] | 
|  | 86 | +    public partial class String : TypeMap | 
|  | 87 | +    { | 
|  | 88 | +        public override Type CLISignatureType(TypePrinterContext ctx) | 
|  | 89 | +        { | 
|  | 90 | +            return new CILType(typeof(string)); | 
|  | 91 | +        } | 
|  | 92 | + | 
|  | 93 | +        public override void CLIMarshalToNative(MarshalContext ctx) | 
|  | 94 | +        { | 
|  | 95 | +            ctx.Return.Write("clix::marshalString<clix::E_UTF8>({0})", | 
|  | 96 | +                ctx.Parameter.Name); | 
|  | 97 | +        } | 
|  | 98 | + | 
|  | 99 | +        public override void CLIMarshalToManaged(MarshalContext ctx) | 
|  | 100 | +        { | 
|  | 101 | +            ctx.Return.Write("clix::marshalString<clix::E_UTF8>({0})", | 
|  | 102 | +                ctx.ReturnVarName); | 
|  | 103 | +        } | 
|  | 104 | +    } | 
|  | 105 | + | 
|  | 106 | +    [TypeMap("std::wstring", GeneratorKind = GeneratorKind.CLI)] | 
|  | 107 | +    public partial class WString : TypeMap | 
|  | 108 | +    { | 
|  | 109 | +        public override Type CLISignatureType(TypePrinterContext ctx) | 
|  | 110 | +        { | 
|  | 111 | +            return new CILType(typeof(string)); | 
|  | 112 | +        } | 
|  | 113 | + | 
|  | 114 | +        public override void CLIMarshalToNative(MarshalContext ctx) | 
|  | 115 | +        { | 
|  | 116 | +            ctx.Return.Write("clix::marshalString<clix::E_UTF16>({0})", | 
|  | 117 | +                ctx.Parameter.Name); | 
|  | 118 | +        } | 
|  | 119 | + | 
|  | 120 | +        public override void CLIMarshalToManaged(MarshalContext ctx) | 
|  | 121 | +        { | 
|  | 122 | +            ctx.Return.Write("clix::marshalString<clix::E_UTF16>({0})", | 
|  | 123 | +                ctx.ReturnVarName); | 
|  | 124 | +        } | 
|  | 125 | +    } | 
|  | 126 | + | 
|  | 127 | +    [TypeMap("std::vector", GeneratorKind = GeneratorKind.CLI)] | 
|  | 128 | +    public partial class Vector : TypeMap | 
|  | 129 | +    { | 
|  | 130 | +        public override bool IsIgnored | 
|  | 131 | +        { | 
|  | 132 | +            get | 
|  | 133 | +            { | 
|  | 134 | +                var finalType = Type.GetFinalPointee() ?? Type; | 
|  | 135 | +                var type = finalType as TemplateSpecializationType; | 
|  | 136 | +                if (type == null) | 
|  | 137 | +                { | 
|  | 138 | +                    var injectedClassNameType = (InjectedClassNameType) finalType; | 
|  | 139 | +                    type = (TemplateSpecializationType) injectedClassNameType.InjectedSpecializationType.Type; | 
|  | 140 | +                } | 
|  | 141 | +                var checker = new TypeIgnoreChecker(TypeMapDatabase); | 
|  | 142 | +                type.Arguments[0].Type.Visit(checker); | 
|  | 143 | + | 
|  | 144 | +                return checker.IsIgnored; | 
|  | 145 | +            } | 
|  | 146 | +        } | 
|  | 147 | + | 
|  | 148 | +        public override Type CLISignatureType(TypePrinterContext ctx) | 
|  | 149 | +        { | 
|  | 150 | +            return new CustomType( | 
|  | 151 | +                $"System::Collections::Generic::List<{ctx.GetTemplateParameterList()}>^"); | 
|  | 152 | +        } | 
|  | 153 | + | 
|  | 154 | +        public override void CLIMarshalToNative(MarshalContext ctx) | 
|  | 155 | +        { | 
|  | 156 | +            var desugared = Type.Desugar(); | 
|  | 157 | +            var templateType = desugared as TemplateSpecializationType; | 
|  | 158 | +            var type = templateType.Arguments[0].Type; | 
|  | 159 | +            var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType(); | 
|  | 160 | +            var managedType = isPointerToPrimitive | 
|  | 161 | +                ? new CILType(typeof(System.IntPtr)) | 
|  | 162 | +                : type.Type; | 
|  | 163 | + | 
|  | 164 | +            var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name | 
|  | 165 | +                : ctx.ArgName; | 
|  | 166 | + | 
|  | 167 | +            var tmpVarName = "_tmp" + entryString; | 
|  | 168 | + | 
|  | 169 | +            var cppTypePrinter = new CppTypePrinter(Context); | 
|  | 170 | +            var nativeType = type.Type.Visit(cppTypePrinter); | 
|  | 171 | + | 
|  | 172 | +            ctx.Before.WriteLine("auto {0} = std::vector<{1}>();", | 
|  | 173 | +                tmpVarName, nativeType); | 
|  | 174 | +            ctx.Before.WriteLine("for each({0} _element in {1})", | 
|  | 175 | +                managedType, entryString); | 
|  | 176 | +            ctx.Before.WriteOpenBraceAndIndent(); | 
|  | 177 | +            { | 
|  | 178 | +                var param = new Parameter | 
|  | 179 | +                { | 
|  | 180 | +                    Name = "_element", | 
|  | 181 | +                    QualifiedType = type | 
|  | 182 | +                }; | 
|  | 183 | + | 
|  | 184 | +                var elementCtx = new MarshalContext(ctx.Context, ctx.Indentation) | 
|  | 185 | +                                     { | 
|  | 186 | +                                         Parameter = param, | 
|  | 187 | +                                         ArgName = param.Name, | 
|  | 188 | +                                     }; | 
|  | 189 | + | 
|  | 190 | +                var marshal = new CLIMarshalManagedToNativePrinter(elementCtx); | 
|  | 191 | +                type.Type.Visit(marshal); | 
|  | 192 | + | 
|  | 193 | +                if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) | 
|  | 194 | +                    ctx.Before.Write(marshal.Context.Before); | 
|  | 195 | + | 
|  | 196 | +                if (isPointerToPrimitive) | 
|  | 197 | +                    ctx.Before.WriteLine("auto _marshalElement = {0}.ToPointer();", | 
|  | 198 | +                        marshal.Context.Return); | 
|  | 199 | +                else | 
|  | 200 | +                    ctx.Before.WriteLine("auto _marshalElement = {0};", | 
|  | 201 | +                    marshal.Context.Return); | 
|  | 202 | + | 
|  | 203 | +                ctx.Before.WriteLine("{0}.push_back(_marshalElement);", | 
|  | 204 | +                    tmpVarName); | 
|  | 205 | +            } | 
|  | 206 | +             | 
|  | 207 | +            ctx.Before.UnindentAndWriteCloseBrace(); | 
|  | 208 | + | 
|  | 209 | +            ctx.Return.Write(tmpVarName); | 
|  | 210 | +        } | 
|  | 211 | + | 
|  | 212 | +        public override void CLIMarshalToManaged(MarshalContext ctx) | 
|  | 213 | +        { | 
|  | 214 | +            var desugared = Type.Desugar(); | 
|  | 215 | +            var templateType = desugared as TemplateSpecializationType; | 
|  | 216 | +            var type = templateType.Arguments[0].Type; | 
|  | 217 | +            var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType(); | 
|  | 218 | +            var managedType = isPointerToPrimitive | 
|  | 219 | +                ? new CILType(typeof(System.IntPtr)) | 
|  | 220 | +                : type.Type; | 
|  | 221 | +            var tmpVarName = "_tmp" + ctx.ArgName; | 
|  | 222 | +             | 
|  | 223 | +            ctx.Before.WriteLine( | 
|  | 224 | +                "auto {0} = gcnew System::Collections::Generic::List<{1}>();", | 
|  | 225 | +                tmpVarName, managedType); | 
|  | 226 | + | 
|  | 227 | +            string retVarName = ctx.ReturnType.Type.Desugar().IsPointer() ? $"*{ctx.ReturnVarName}" : ctx.ReturnVarName; | 
|  | 228 | +            ctx.Before.WriteLine("for(auto _element : {0})", | 
|  | 229 | +                retVarName); | 
|  | 230 | +            ctx.Before.WriteOpenBraceAndIndent(); | 
|  | 231 | +            { | 
|  | 232 | +                var elementCtx = new MarshalContext(ctx.Context, ctx.Indentation) | 
|  | 233 | +                                     { | 
|  | 234 | +                                         ReturnVarName = "_element", | 
|  | 235 | +                                         ReturnType = type | 
|  | 236 | +                                     }; | 
|  | 237 | + | 
|  | 238 | +                var marshal = new CLIMarshalNativeToManagedPrinter(elementCtx); | 
|  | 239 | +                type.Type.Visit(marshal); | 
|  | 240 | + | 
|  | 241 | +                if (!string.IsNullOrWhiteSpace(marshal.Context.Before)) | 
|  | 242 | +                    ctx.Before.Write(marshal.Context.Before); | 
|  | 243 | + | 
|  | 244 | +                ctx.Before.WriteLine("auto _marshalElement = {0};", | 
|  | 245 | +                    marshal.Context.Return); | 
|  | 246 | + | 
|  | 247 | +                if (isPointerToPrimitive) | 
|  | 248 | +                    ctx.Before.WriteLine("{0}->Add({1}(_marshalElement));", | 
|  | 249 | +                        tmpVarName, managedType); | 
|  | 250 | +                else | 
|  | 251 | +                    ctx.Before.WriteLine("{0}->Add(_marshalElement);", | 
|  | 252 | +                        tmpVarName); | 
|  | 253 | +            } | 
|  | 254 | +            ctx.Before.UnindentAndWriteCloseBrace(); | 
|  | 255 | + | 
|  | 256 | +            ctx.Return.Write(tmpVarName); | 
|  | 257 | +        } | 
|  | 258 | +    } | 
|  | 259 | + | 
|  | 260 | +    [TypeMap("std::map", GeneratorKind = GeneratorKind.CLI)] | 
|  | 261 | +    public partial class Map : TypeMap | 
|  | 262 | +    { | 
|  | 263 | +        public override bool IsIgnored { get { return true; } } | 
|  | 264 | + | 
|  | 265 | +        public override Type CLISignatureType(TypePrinterContext ctx) | 
|  | 266 | +        { | 
|  | 267 | +            var type = Type as TemplateSpecializationType; | 
|  | 268 | +            return new CustomType( | 
|  | 269 | +                $@"System::Collections::Generic::Dictionary<{ | 
|  | 270 | +                    type.Arguments[0].Type}, {type.Arguments[1].Type}>^"); | 
|  | 271 | +        } | 
|  | 272 | + | 
|  | 273 | +        public override void CLIMarshalToNative(MarshalContext ctx) | 
|  | 274 | +        { | 
|  | 275 | +            throw new System.NotImplementedException(); | 
|  | 276 | +        } | 
|  | 277 | + | 
|  | 278 | +        public override void CLIMarshalToManaged(MarshalContext ctx) | 
|  | 279 | +        { | 
|  | 280 | +            throw new System.NotImplementedException(); | 
|  | 281 | +        } | 
|  | 282 | + | 
|  | 283 | +        public override Type CSharpSignatureType(TypePrinterContext ctx) | 
|  | 284 | +        { | 
|  | 285 | +            if (ctx.Kind == TypePrinterContextKind.Native) | 
|  | 286 | +                return new CustomType("Std.Map"); | 
|  | 287 | + | 
|  | 288 | +            var type = Type as TemplateSpecializationType; | 
|  | 289 | +            return new CustomType( | 
|  | 290 | +                $@"System.Collections.Generic.Dictionary<{ | 
|  | 291 | +                    type.Arguments[0].Type}, {type.Arguments[1].Type}>"); | 
|  | 292 | +        } | 
|  | 293 | +    } | 
|  | 294 | + | 
|  | 295 | +    [TypeMap("std::list", GeneratorKind = GeneratorKind.CLI)] | 
|  | 296 | +    public partial class List : TypeMap | 
|  | 297 | +    { | 
|  | 298 | +        public override bool IsIgnored { get { return true; } } | 
|  | 299 | +    } | 
|  | 300 | + | 
|  | 301 | +    [TypeMap("std::shared_ptr", GeneratorKind = GeneratorKind.CLI)] | 
|  | 302 | +    public partial class SharedPtr : TypeMap | 
|  | 303 | +    { | 
|  | 304 | +        public override bool IsIgnored { get { return true; } } | 
|  | 305 | +    } | 
|  | 306 | + | 
|  | 307 | +    [TypeMap("basic_ostream<char, char_traits<char>>", GeneratorKind.CLI)] | 
|  | 308 | +    public partial class OStream : TypeMap | 
|  | 309 | +    { | 
|  | 310 | +        public override Type CLISignatureType(TypePrinterContext ctx) | 
|  | 311 | +        { | 
|  | 312 | +            return new CILType(typeof(System.IO.TextWriter)); | 
|  | 313 | +        } | 
|  | 314 | + | 
|  | 315 | +        public override void CLIMarshalToNative(MarshalContext ctx) | 
|  | 316 | +        { | 
|  | 317 | +            var marshal = (CLIMarshalManagedToNativePrinter) ctx.MarshalToNative; | 
|  | 318 | +            if (!ctx.Parameter.Type.Desugar().IsPointer()) | 
|  | 319 | +                marshal.ArgumentPrefix.Write("*"); | 
|  | 320 | +            var marshalCtxName = string.Format("ctx_{0}", ctx.Parameter.Name); | 
|  | 321 | +            ctx.Before.WriteLine("msclr::interop::marshal_context {0};", marshalCtxName); | 
|  | 322 | +            ctx.Return.Write("{0}.marshal_as<std::ostream*>({1})", | 
|  | 323 | +                marshalCtxName, ctx.Parameter.Name); | 
|  | 324 | +        } | 
|  | 325 | +    } | 
|  | 326 | + | 
|  | 327 | +    [TypeMap("std::nullptr_t", GeneratorKind = GeneratorKind.CLI)] | 
|  | 328 | +    public partial class NullPtr : TypeMap | 
|  | 329 | +    { | 
|  | 330 | +        public override bool DoesMarshalling { get { return false; } } | 
|  | 331 | + | 
|  | 332 | +        public override void CLITypeReference(CLITypeReferenceCollector collector, | 
|  | 333 | +            ASTRecord<Declaration> loc) | 
|  | 334 | +        { | 
|  | 335 | +            var typeRef = collector.GetTypeReference(loc.Value); | 
|  | 336 | + | 
|  | 337 | +            if (typeRef != null) | 
|  | 338 | +            { | 
|  | 339 | +                var include = new CInclude | 
|  | 340 | +                { | 
|  | 341 | +                    File = "cstddef", | 
|  | 342 | +                    Kind = CInclude.IncludeKind.Angled, | 
|  | 343 | +                }; | 
|  | 344 | + | 
|  | 345 | +                typeRef.Include = include; | 
|  | 346 | +            } | 
|  | 347 | +        } | 
|  | 348 | +    } | 
|  | 349 | +} | 
0 commit comments