PRB: Visual Basic and Visual Basic for Applications Do Not Understand IUnknown** Data Type in MIDL Type Library (194913)
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.
REFERENCES
For more information on using MIDL or MkTypLib, see the "Automation" section in the MSDN library on the following Microsoft Web site at:
Modification Type: | Major | Last Reviewed: | 5/13/2003 |
---|
Keywords: | kbAutomation kbpending kbprb KB194913 kbAudDeveloper |
---|
|