Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Variable uses a type not supported in Visual Basic (Error 458)

397 views
Skip to first unread message

Radu Enuca

unread,
May 31, 2004, 8:06:58 AM5/31/04
to
Hi,

I have the following problem. I'm designing an ActiveX control in vb6
that uses a lot of API's.
It runs well when I test it from a test project in the same project
group but when I want to compile it I have this error:
"Variable uses a type not supported in Visual Basic (Error 458)"

I found on internet that API's that use as input parameter a type like
"Any" can cause that problem but I'm using API for more than 2 years and I
never had this problem before (I even tried to replece As Any with As Long
but no results).

I also have an interface that exposes several variant properties. I'm
suspecting that this can be the cause but woks fine till I want to compile
it.

Any help please ???

Thanks in advance

Duane Bozarth

unread,
May 31, 2004, 8:50:31 AM5/31/04
to

Not until you show the details of the call/declare for the offending
routines...

Radu Enuca

unread,
May 31, 2004, 10:20:11 AM5/31/04
to
The problem is that the error message points no where.

Public Property Let List(ByRef Value As Variant)

End Property

Public Property Get List() As Variant

End Property

This is a property in an Interfce called IFreeControl that accepts and
returns a variant. I replaced variant with string and worked

It is possible that VB cannot write in the TLB a function that returns a
variant ???

"Duane Bozarth" <dp_bo...@swko.dot.net> wrote in message
news:40BB2A17...@swko.dot.net...

Randy Birch

unread,
May 31, 2004, 5:40:44 PM5/31/04
to
Knowledge Base

PRB: Visual Basic and Visual Basic for Applications Do Not Understand
IUnknown** Data Type in MIDL Type Library

PSS ID Number: 194913

Article Last Modified on 5/13/2003

--------------------------------------------------------------------------------
The information in this article applies to:

Microsoft Visual Basic Learning Edition for Windows 5.0
Microsoft Visual Basic Learning Edition for Windows 6.0
Microsoft Visual Basic Professional Edition for Windows 5.0
Microsoft Visual Basic Professional Edition for Windows 6.0
Microsoft Visual Basic Enterprise Edition for Windows 5.0
Microsoft Visual Basic Enterprise Edition for Windows 6.0
Microsoft Visual Basic for Applications (VBA) Software Development Kit (SDK)
5.0
Microsoft Visual Basic for Applications (VBA) Software Development Kit (SDK)
6.0
Microsoft Visual C++, 32-bit Enterprise Edition 5.0
Microsoft Visual C++, 32-bit Enterprise Edition 6.0

--------------------------------------------------------------------------------

This article was previously published under Q194913

SYMPTOMS
If you build a Component Object Model (COM) component in C/C++ that takes or
returns an IUnknown** data type and uses an Interface Definition Language
(IDL) file and the Microsoft Interface Definition Language (MIDL) compiler
to generate the type library, you find that neither Visual Basic nor Visual
Basic for Applications (VBA) display the type correctly in the Visual Basic
Object Browser, and indicate that the type is UNKNOWN.

When you call the C/C++ component from Visual Basic, you may see the
following run-time error:
Run-time error: 458


Variable uses a type not supported in Visual Basic

This error message can occur during cross-apartment calls to the interface.
At other times, the method call succeeds even though Visual Basic is unsure
of the data type.

In addition, if you use the Implements keyword to implement the C/C++
interface in a Visual Basic class, you receive the following compile-time
error message:
Bad interface for Implements: method uses type that is not supported by
Visual Basic.
You cannot implement an interface with an UNKNOWN type.

However, a similarly written Visual Basic component that uses the hidden
IUnknown data type (which equates to an IUnknown** in C/C++) displays
correctly in the Object Browser and can be called by another Visual Basic
class or used by Visual Basic Implements without error.

CAUSE
MIDL-generated type libraries represent an IUnknown** parameter as a
VT_UNKNOWN in the TYPEDESC for the ELEMDESC struct that describes the
parameter. Although Visual Basic can work with VARIANTs of type VT_UNKNOWN,
it does not expect this type for a parameter description in a type library.
Consequently, it treats the parameter as UNKNOWN, and displays one of the
error messages in the "Symptoms" section of this article.

Visual Basic and VBA both use the CreateTypeLib2 API function (not MIDL) to
generate the type library when they build their own COM components, and they
can define a parameter as being the type IUnknown** by using a reference to
an external type library (stdole2.tlb) and a ITypeInfo to describe the data
type. The reference points to the actual description of IUnknown instead of
relying on the VT_UNKNOWN VARTYPE.

RESOLUTION
Because programmers are not allowed to use an IUnknown** data type natively
in Visual Basic and VBA, components that are designed to work in these
programming environments should avoid using this type when possible. Two
common reasons why you might have chosen to use IUnknown in your component
description (but you don't actually need to) are:
When you want to implement a polymorphic property or method that can take
any object. Because Visual Basic cannot use an IUnknown pointer natively, it
is better to use IDispatch and return only dual (or dispinterface) objects.
These objects appear as Object in Visual Basic and can be treated
polymorphically, which accomplishes the same effect in a more Visual
Basic-oriented fashion.

If you need to pass a custom interface that is not dual, a common, shared
interface type can be defined and inherited by this interface (and all other
objects that are passed) and define the method or property as taking this
shared base interface (rather than IUnknown). As long as the new base
interface is described in the type library, Visual Basic and VBA can use it
without a problem.

When you want to pass a generic collection item; for example, the Visual
Basic-style _NewEnum property that returns an IUnknown**, or a standard OLE
interface that is not dual. In this case, you should use the actual
interface type that is being passed rather than the more generic IUnknown.
For example, the _NewEnum property should return an IEnumVARIANT*, because
this is, in fact, the interface that Visual Basic needs and expects. When it
is compiled with MIDL, this interface type is cross-referenced to its
definition in stdole2.tlb, and you do not receive an error message.

If you are not faced with either of the previous situations, or if you must
have an IUnknown** declaration, Visual Basic can accept this type, but it
must be fully qualified with the stdole library (that is,
stdole.IUnknown**). This cannot be done in IDL and compiled with MIDL.

While you can qualify data types in MIDL, the MIDL compiler automatically
converts any qualified reference to IUnknown back to a VT_UNKNOWN VARTYPE in
the type library description. This simplifies the library for remote
procedure calls (RPC) and DCOM, but it prevents you from using MIDL to
generate libraries that use a Visual Basic- or Visual Basic for
Applications-compatible IUnknown** type. Instead, you need to use MkTypLib
and an ODL file to build the type library, or create the library
programmatically with the CreateTypeLib2 API. See the "More Information"
section for details.

STATUS
This problem is a compatibility issue between Microsoft Visual Basic and the
Microsoft MIDL compiler.

MORE INFORMATION
Steps to Reproduce Behavior
Open Visual C++ and, on the File menu, click New. On the Projects tab,
select Win32 Dynamic-Link Library, and name the project MyUnknown. Keep the
defaults in any dialog boxes that may appear.
On the File menu, click New, and then select Text File on the Files tab.
Name the file MyUnknown.odl, and then click OK.
Add the following code to MyUnknown.odl:
[
uuid(1A4C3A6A-50AE-11D1-BB71-00C04FAD8B08),
version(1.1)
]
library MyUnknown
{
importlib("StdOle2.tlb");

[
odl,
uuid(1A4C3A68-50AE-11D1-BB71-00C04FAD8B08),
hidden
]
interface _CTUnknown : IUnknown {
HRESULT GetIUnknown([out, retval] IUnknown** iu);
HRESULT SetIUnknown([in, out] IUnknown** iu);
};

[
uuid(1A4C3A69-50AE-11D1-BB71-00C04FAD8B08)
]
coclass CTUnknown {
[default] interface _CTUnknown;
};

};

Press the CTRL+F7 keys or select Compile MyUnknown.odl from the Build menu
to build the type library.

Open Visual Basic and select a new Standard EXE project. On the Project
menu, choose References, and then click Browse. Find your compiled type
library (MyUnknown.tlb) in the debug directory of your Visual C++ project
and click OK. Make sure that the library is checked in the References dialog
box, and then click OK to close the References dialog box.

Open the Visual Basic Object Browser by pressing F2. Select MyUnknown from
the drop-down list box on the upper-left portion of the Object Browser. View
the SetIUnknown and GetIUnknown functions of the MyUnknown.CTUnknown class,
and note that Visual Basic identifies the IUnknown** parameters as type
"Unknown," and cannot read them.

Close your Visual Basic project. Do not save changes.

To correct the problem, return to Visual C++ and modify the MyUnknown.odl
file by changing the GetIUnknown and SetIUnknown functions to read:
HRESULT GetIUnknown([out, retval] stdole.IUnknown** iu);
HRESULT SetIUnknown([in, out] stdole.IUnknown** iu);

In the project workspace, click the File View tab. Double-click MyUnknown
Files to expand the file tree. Right-click the MyUnknown.odl file, and then
select Settings on the Context menu.

On the Project Settings dialog box, choose the General Tab, and then check
the Always use custom build step option. Choose the Custom Build tab, and
then add the following to the Build command(s) line:

mktyplib MyUnknown.odl /tlb "Debug\MyUnknown.tlb"

Add the following to the Output file(s) line, and then click OK:
Debug\MyUnknown.tlb

Rebuild your type library by pressing CTRL+F7 or selecting Compile
MyUnknown.odl on the Build menu.
Repeat steps 5 and 6 to verify that Visual Basic can now recognize the
IUnknown** data types.
Problems with the Use of MkTypLib
Microsoft has standardized on the MIDL compiler for all new COM and COM+
applications, and encourages developers to use MIDL whenever possible.

Developers who do use MkTypLib to work around this issue should be aware
that MkTypLib does not allow you to compile an interface with the qualified
stdole.IUnknown** type if the interface is marked "oleautomation
compatible." You need to remove the oleautomation attribute to compile the
type library. However, if you remove oleautomation, you are not able to use
the universal marshaller (typelib marshalling) to remote the interface
across contexts. So, in addition to using an MkTypLib library for your type
information, you need to build a proxy DLL (or custom marshal with IMarshal)
to handle any remoting of the interface.

Furthermore, MkTypLib offers only a limited set of functionality in defining
your interfaces. If your project requires IDL-specific definitions (such as
wire_marshal, iid_is, asynch, and so forth) or the __int64 data type, you
cannot use MkTypLib. You need to restructure the interface description as
outlined in the "Resolution" section of this article, or build your own
library with the CreateTypeLib2 API.

REFERENCES
For more information on using MIDL or MkTypLib, see the "Automation" section
in the MSDN library on the following Microsoft Web site at:
http://msdn.microsoft.com/library/psdk/automat/autoportal_7l45.htm


--

Randy Birch
MVP Visual Basic
http://vbnet.mvps.org/
Please respond only to the newsgroups so all can benefit.


"Radu Enuca" <radu....@NOSPAM.infoworld.ro.NOSPAM> wrote in message
news:OyWnKHxR...@TK2MSFTNGP11.phx.gbl...
: The problem is that the error message points no where.

:


Radu Enuca

unread,
Jun 1, 2004, 3:53:05 AM6/1/04
to
Thank you very much !!!
"Randy Birch" <rgb_rem...@mvps.org> wrote in message
news:Okjvuf1R...@TK2MSFTNGP09.phx.gbl...
0 new messages