public void HandleRefOutPrimitiveType(PrimitiveType type, Enumeration @enum = null)
        {
            TypePrinter.PushContext(TypePrinterContextKind.Native);
            var typeName = Context.Parameter.Visit(TypePrinter);

            TypePrinter.PopContext();

            // Perform null checking for all primitive value types.
            string extraCheck = (type != PrimitiveType.String && Context.Parameter.IsInOut) ?
                                $" || {Context.ArgName}.get() == null" : string.Empty;

            Context.SupportBefore.WriteLine($"if ({Context.ArgName} == null{extraCheck})");
            Context.SupportBefore.WriteLineIndent($"throw new NullRefParameterException(\"{Context.Parameter.Name}\");");

            string marshal = $"{Context.ArgName}.get()";

            var isEnum = @enum != null;

            if (isEnum)
            {
                marshal = $"{marshal}.getValue()";
            }

            if (type == PrimitiveType.Bool)
            {
                marshal = $"((byte) ({marshal} ? 1 : 0))";
            }

            var varName = JavaGenerator.GeneratedIdentifier(Context.ArgName);

            Context.SupportBefore.Write($"{typeName} {varName} = ");

            if (isEnum || type == PrimitiveType.Bool)
            {
                Context.SupportBefore.WriteLine($"new {typeName}({marshal});");
            }
            else
            {
                Context.SupportBefore.WriteLine($"({marshal}) != null ? new {typeName}({marshal}) : new {typeName}();");
            }

            Context.Return.Write(varName);

            var value = $"{varName}.getValue()";

            marshal = value;

            if (isEnum)
            {
                marshal = $"{@enum.Name}.fromOrdinal({value})";
            }

            if (type == PrimitiveType.Bool)
            {
                marshal = $"{value} != 0";
            }

            Context.SupportAfter.WriteLine($"{Context.ArgName}.set({marshal});");
        }
        public static IEnumerable<string> GetPackageNames(Declaration decl)
        {
            var namespaces = Declaration.GatherNamespaces(decl.Namespace)
                .Where(ns => !(ns is TranslationUnit));

            var names = namespaces.Select(n => n.Name.ToLowerInvariant()).ToList();
            names.Insert(0, JavaGenerator.GetNativeLibPackageName(decl.TranslationUnit));

            return names;
        }
        public override bool VisitEnumDecl(Enumeration @enum)
        {
            if (IsByRefParameter)
            {
                HandleRefOutPrimitiveType(@enum.BuiltinType.Type, @enum);
                return(true);
            }

            var typeName = @enum.BuiltinType.Visit(TypePrinter);
            var varName  = JavaGenerator.GeneratedIdentifier(Context.ArgName);

            Context.SupportBefore.WriteLine($"{typeName} {varName} = {Context.ArgName}.getValue();");

            Context.Return.Write(varName);
            return(true);
        }
        public override bool VisitClassDecl(Class @class)
        {
            if (!VisitDeclaration(@class))
                return false;

            GenerateClassSpecifier(@class);

            Write(" ");
            WriteStartBraceIndent();

            var hasNonInterfaceBase = @class.HasBaseClass && @class.BaseClass.IsGenerated
                && [email protected];

            var objectIdent = JavaGenerator.GeneratedIdentifier("object");

            if ([email protected] && [email protected])
            {
                if (!hasNonInterfaceBase)
                {
                    WriteLine($"public {JavaGenerator.IntPtrType} {objectIdent};");
                    NewLine();
                }
                
                Write($"public {@class.Name}({JavaGenerator.IntPtrType} object) {{ ");
                WriteLine(hasNonInterfaceBase ? "super(object); }" : $"this.{objectIdent} = object; }}");
                NewLine();

                var implementsInterfaces = @class.Bases.Any(b => b.Class.IsGenerated && b.Class.IsInterface);
                if (implementsInterfaces)
                {
                    WriteLine("@Override");
                    WriteLine($"public com.sun.jna.Pointer __getObject() {{ return this.{objectIdent}; }}");
                    NewLine();
                }
            }

            VisitDeclContext(@class);
            WriteCloseBraceIndent();

            return true;
        }
        public override bool VisitClassDecl(Class @class)
        {
            var @object   = IsByRefParameter ? $"{Context.ArgName}.get()" : Context.ArgName;
            var objectRef = @class.IsInterface ? "__getObject()" : "__object";

            if (IsByRefParameter)
            {
                CheckRefOutParameter(Context.Parameter.IsInOut);

                TypePrinter.PushContext(TypePrinterContextKind.Native);
                var typeName = Context.Parameter.Visit(TypePrinter);
                TypePrinter.PopContext();

                var varName = JavaGenerator.GeneratedIdentifier(Context.ArgName);
                var marshal = Context.Parameter.IsInOut ?
                              $"new {typeName}({@object}.{objectRef})" : $"new {typeName}()";
                Context.SupportBefore.WriteLine($"{typeName} {varName} = {marshal};");

                var marshalContext = new MarshalContext(Context.Context)
                {
                    Parameter     = Context.Parameter,
                    ReturnVarName = $"{varName}.getValue()"
                };

                var marshaler = new JavaMarshalNativeToManaged(marshalContext);
                @class.Visit(marshaler);

                Context.SupportAfter.WriteLine($"{Context.ArgName}.set({marshaler.Context.Return});");

                Context.Return.Write(varName);
                return(true);
            }

            Context.Return.Write($"{Context.ArgName} == null ? null : {Context.ArgName}.{objectRef}");
            return(true);
        }
        public void HandleRefOutPrimitiveType(PrimitiveType type, Enumeration @enum = null)
        {
            TypePrinter.PushContext(TypePrinterContextKind.Native);
            var typeName = Context.Parameter.Visit(TypePrinter);

            TypePrinter.PopContext();

            CheckRefOutParameter(type != PrimitiveType.String && Context.Parameter.IsInOut);

            string marshal = $"{Context.ArgName}.get()";

            var isEnum = @enum != null;

            if (isEnum)
            {
                marshal = $"{marshal}.getValue()";
            }

            if (type == PrimitiveType.Bool)
            {
                marshal = $"((byte) ({marshal} ? 1 : 0))";
            }

            if (IsReferenceIntegerType(type))
            {
                var integerTypeName = TypePrinter.VisitPrimitiveType(GetSignedIntegerType(type));
                marshal = $"({integerTypeName}){marshal}.intValue()";
            }

            var varName = JavaGenerator.GeneratedIdentifier(Context.ArgName);

            Context.SupportBefore.Write($"{typeName} {varName} = ");

            if (isEnum || type == PrimitiveType.Bool || IsReferenceIntegerType(type))
            {
                Context.SupportBefore.WriteLine($"new {typeName}({marshal});");
            }
            else
            {
                Context.SupportBefore.WriteLine($"({marshal}) != null ? new {typeName}({marshal}) : new {typeName}();");
            }

            Context.Return.Write(varName);

            var value = $"{varName}.getValue()";

            marshal = value;

            if (isEnum)
            {
                marshal = $"{@enum.Visit(TypePrinter)}.fromOrdinal({value})";
            }

            if (type == PrimitiveType.Bool)
            {
                marshal = $"{value} != 0";
            }

            if (IsReferenceIntegerType(type))
            {
                var integerTypeName = Context.Parameter.Type.Visit(TypePrinter);
                marshal = $"new {integerTypeName}({value})";
            }

            Context.SupportAfter.WriteLine($"{Context.ArgName}.set({marshal});");
        }