public static TypeBinding bind( Generator g, IType t, String nameHint ) throws BindingException {
        IPrimitiveType pt = t.queryInterface(IPrimitiveType.class);
        if(pt!=null) {
            // primitive
            TypeBinding r = primitiveTypeBindings.get(pt.getVarType());
            if(r!=null)     return r;

            throw new BindingException(Messages.UNSUPPORTED_VARTYPE.format(pt.getVarType()));
        }

        IPtrType ptrt = t.queryInterface(IPtrType.class);
        if(ptrt!=null) {
            // pointer type
            IType comp = ptrt.getPointedAtType();
            IInterfaceDecl compDecl = comp.queryInterface(IInterfaceDecl.class);
            if( compDecl!=null ) {
                // t = T* where T is a declared interface
                return new TypeBinding( g.getTypeName(compDecl), NativeType.ComObject, true );
            }

            IDispInterfaceDecl dispDecl = comp.queryInterface(IDispInterfaceDecl.class);
            if( dispDecl!=null ) {
                // t = T* where T is a declared interface
                return new TypeBinding( g.getTypeName(dispDecl), NativeType.ComObject,  true );
            }

            // t = coclass*
            ICoClassDecl classdecl = comp.queryInterface(ICoClassDecl.class);
            if(classdecl!=null) {
                // bind to its default interface
                ITypeDecl di = g.getDefaultInterface(classdecl);
                if(di==null)
                    // no primary interface known. treat it as IUnknown
                    return new TypeBinding(Com4jObject.class, NativeType.ComObject, true);
                else
                    return new TypeBinding( g.getTypeName(di), NativeType.ComObject, true );
            }

            IPrimitiveType compPrim = comp.queryInterface(IPrimitiveType.class);
            if( compPrim!=null ) {
                // T = PRIMITIVE*
                if( compPrim.getVarType()== VarType.VT_VARIANT ) {
                    // T = VARIANT*
                    return new TypeBinding(Object.class, NativeType.VARIANT_ByRef, true);
                }
                if( compPrim.getVarType()==VarType.VT_VOID ) {
                    // T = void*
                    return new TypeBinding(Buffer.class,  NativeType.PVOID, true );
                }
                if( compPrim.getVarType()==VarType.VT_UI2 ) {
                    // T = ushort*
                    if( isPsz(nameHint) )
                        // this is a common mistake
                        return new TypeBinding( String.class, NativeType.Unicode, false );
                }
                if( compPrim.getVarType()==VarType.VT_BOOL ) {
                    return new TypeBinding("Holder<Boolean>", NativeType.VariantBool_ByRef, true );
                }
            }

            ISafeArrayType at = comp.queryInterface(ISafeArrayType.class);
            if(at!=null) {
                // T=SAFEARRAY(...)
                IType comp2 = at.getComponentType();

                IPrimitiveType compPrim2 = comp2.queryInterface(IPrimitiveType.class);
                if( compPrim2!=null ) {
                    TypeBinding r = primitiveTypeBindings.get(compPrim2.getVarType());
                    if(r!=null) {
                        return new TypeBinding("Holder<"+r.javaType+"[]>", NativeType.SafeArray, true );
                    }
                }
                TypeBinding tb = TypeBinding.bind(g, comp2, null);
                if(tb.nativeType == NativeType.VARIANT){
                  return new TypeBinding("Holder<Object[]>", NativeType.SafeArray, true);
                }
            }

            // a few other random checks
            String name = getTypeString(ptrt);
            if( name.equals("_RemotableHandle*") ) {
                // marshal as the raw pointer value
                return new TypeBinding( Integer.TYPE, NativeType.Int32,  true );
            }
            if(name.equals("GUID*")) {
                return new TypeBinding( "GUID", NativeType.GUID, true );
            }

            // otherwise use a holder
            TypeBinding b = bind(g,comp,null);
            if(b!=null && b.nativeType.byRef()!=null )
                return b.createByRef();
        }

        ISafeArrayType at = t.queryInterface(ISafeArrayType.class);
        if(at!=null) {
            // T=SAFEARRAY(...)
            IType comp = at.getComponentType();

            IPrimitiveType compPrim = comp.queryInterface(IPrimitiveType.class);
            if( compPrim!=null ) {
                TypeBinding r = primitiveTypeBindings.get(compPrim.getVarType());
                if(r!=null) {
                    return new TypeBinding(r.javaType+"[]", NativeType.SafeArray, true );
                }
            }
            TypeBinding tb = TypeBinding.bind(g, comp, null);
            if(tb.nativeType == NativeType.VARIANT){
              return new TypeBinding("Object[]", NativeType.SafeArray, true);
            }
        }

        // T = typedef
        ITypedefDecl typedef = t.queryInterface(ITypedefDecl.class);
        if(typedef!=null) {
            return bind(g,typedef.getDefinition(),nameHint);
        }

        // T = enum
        IEnumDecl enumdef = t.queryInterface(IEnumDecl.class);
        if(enumdef!=null) {
            // TODO: we should probably check the size of the enum.
            // there's no guarantee it's 32 bit.
            return new TypeBinding( g.getTypeName(enumdef), NativeType.Int32, true );
        }

        // a few other random checks
        String name = getTypeString(t);
        if(name.equals("GUID")) {
            return new TypeBinding( "GUID", NativeType.GUID, true );
        }

        IDispInterfaceDecl disp = t.queryInterface(IDispInterfaceDecl.class);
        if(disp != null) {
            // TODO check this: this is a dispatch interface, so bind to Com4jObject?
            if(disp.getGUID().equals(COM4J.IID_IPictureDisp)){
                return new TypeBinding(IPictureDisp.class, NativeType.ComObject, true);
            }
            if(disp.getGUID().equals(COM4J.IID_IFontDisp)){
                return new TypeBinding(IFontDisp.class, NativeType.ComObject, true);
            }
            // TODO: not clear how we should handle this
            throw new BindingException(Messages.UNSUPPORTED_TYPE.format(getTypeString(t)));
        }

        ITypeDecl declt = t.queryInterface(ITypeDecl.class);
        if(declt!=null) {
            // TODO: not clear how we should handle this
            throw new BindingException(Messages.UNSUPPORTED_TYPE.format(getTypeString(t)));
        }

        throw new BindingException(Messages.UNSUPPORTED_TYPE.format(getTypeString(t)));
    }
public static TypeBinding bind ( Generator g , IType t , String nameHint ) throws BindingException { IPrimitiveType pt = t . queryInterface ( IPrimitiveType . class ) ; if ( pt != null ) { TypeBinding r = primitiveTypeBindings . get ( pt . getVarType ( ) ) ; if ( r != null ) return r ; throw new BindingException ( Messages . UNSUPPORTED_VARTYPE . format ( pt . getVarType ( ) ) ) ; } IPtrType ptrt = t . queryInterface ( IPtrType . class ) ; if ( ptrt != null ) { IType comp = ptrt . getPointedAtType ( ) ; IInterfaceDecl compDecl = comp . queryInterface ( IInterfaceDecl . class ) ; if ( compDecl != null ) { return new TypeBinding ( g . getTypeName ( compDecl ) , NativeType . ComObject , true ) ; } IDispInterfaceDecl dispDecl = comp . queryInterface ( IDispInterfaceDecl . class ) ; if ( dispDecl != null ) { return new TypeBinding ( g . getTypeName ( dispDecl ) , NativeType . ComObject , true ) ; } ICoClassDecl classdecl = comp . queryInterface ( ICoClassDecl . class ) ; if ( classdecl != null ) { ITypeDecl di = g . getDefaultInterface ( classdecl ) ; if ( di == null ) return new TypeBinding ( Com4jObject . class , NativeType . ComObject , true ) ; else return new TypeBinding ( g . getTypeName ( di ) , NativeType . ComObject , true ) ; } IPrimitiveType compPrim = comp . queryInterface ( IPrimitiveType . class ) ; if ( compPrim != null ) { if ( compPrim . getVarType ( ) == VarType . VT_VARIANT ) { return new TypeBinding ( Object . class , NativeType . VARIANT_ByRef , true ) ; } if ( compPrim . getVarType ( ) == VarType . VT_VOID ) { return new TypeBinding ( Buffer . class , NativeType . PVOID , true ) ; } if ( compPrim . getVarType ( ) == VarType . VT_UI2 ) { if ( isPsz ( nameHint ) ) return new TypeBinding ( String . class , NativeType . Unicode , false ) ; } if ( compPrim . getVarType ( ) == VarType . VT_BOOL ) { return new TypeBinding ( "Holder<Boolean>" , NativeType . VariantBool_ByRef , true ) ; } } ISafeArrayType at = comp . queryInterface ( ISafeArrayType . class ) ; if ( at != null ) { IType comp2 = at . getComponentType ( ) ; IPrimitiveType compPrim2 = comp2 . queryInterface ( IPrimitiveType . class ) ; if ( compPrim2 != null ) { TypeBinding r = primitiveTypeBindings . get ( compPrim2 . getVarType ( ) ) ; if ( r != null ) { return new TypeBinding ( "Holder<" + r . javaType + "[]>" , NativeType . SafeArray , true ) ; } } TypeBinding tb = TypeBinding . bind ( g , comp2 , null ) ; if ( tb . nativeType == NativeType . VARIANT ) { return new TypeBinding ( "Holder<Object[]>" , NativeType . SafeArray , true ) ; } } String name = getTypeString ( ptrt ) ; if ( name . equals ( "_RemotableHandle*" ) ) { return new TypeBinding ( Integer . TYPE , NativeType . Int32 , true ) ; } if ( name . equals ( "GUID*" ) ) { return new TypeBinding ( "GUID" , NativeType . GUID , true ) ; } TypeBinding b = bind ( g , comp , null ) ; if ( b != null && b . nativeType . byRef ( ) != null ) return b . createByRef ( ) ; } ISafeArrayType at = t . queryInterface ( ISafeArrayType . class ) ; if ( at != null ) { IType comp = at . getComponentType ( ) ; IPrimitiveType compPrim = comp . queryInterface ( IPrimitiveType . class ) ; if ( compPrim != null ) { TypeBinding r = primitiveTypeBindings . get ( compPrim . getVarType ( ) ) ; if ( r != null ) { return new TypeBinding ( r . javaType + "[]" , NativeType . SafeArray , true ) ; } } TypeBinding tb = TypeBinding . bind ( g , comp , null ) ; if ( tb . nativeType == NativeType . VARIANT ) { return new TypeBinding ( "Object[]" , NativeType . SafeArray , true ) ; } } ITypedefDecl typedef = t . queryInterface ( ITypedefDecl . class ) ; if ( typedef != null ) { return bind ( g , typedef . getDefinition ( ) , nameHint ) ; } IEnumDecl enumdef = t . queryInterface ( IEnumDecl . class ) ; if ( enumdef != null ) { return new TypeBinding ( g . getTypeName ( enumdef ) , NativeType . Int32 , true ) ; } String name = getTypeString ( t ) ; if ( name . equals ( "GUID" ) ) { return new TypeBinding ( "GUID" , NativeType . GUID , true ) ; } IDispInterfaceDecl disp = t . queryInterface ( IDispInterfaceDecl . class ) ; if ( disp != null ) { if ( disp . getGUID ( ) . equals ( COM4J . IID_IPictureDisp ) ) { return new TypeBinding ( IPictureDisp . class , NativeType . ComObject , true ) ; } if ( disp . getGUID ( ) . equals ( COM4J . IID_IFontDisp ) ) { return new TypeBinding ( IFontDisp . class , NativeType . ComObject , true ) ; } throw new BindingException ( Messages . UNSUPPORTED_TYPE . format ( getTypeString ( t ) ) ) ; } ITypeDecl declt = t . queryInterface ( ITypeDecl . class ) ; if ( declt != null ) { throw new BindingException ( Messages . UNSUPPORTED_TYPE . format ( getTypeString ( t ) ) ) ; } throw new BindingException ( Messages . UNSUPPORTED_TYPE . format ( getTypeString ( t ) ) ) ; }
Binds the native type to a Java type and its conversion.

@param nameHint
Optional parameter name of the type. If non-null,
this is used to disambiguate common mistake
like declaring LPWSTR as "ushort*", etc.