Discussion:
MIDL2039: interface does not conform to [oleautomation] attribute
(too old to reply)
TxITGuy
2005-06-14 17:08:02 UTC
Permalink
Hello,

I am having a curious (and mildly frustrating) problem with a COM component
I am writing in C++. Every method and event works flawlessly in both the
ActiveX Control Test container and in a Visual Basic application. I just
tried to add my first property (get, read-only) to the class, though, and
can't figure out how to get Visual Basic to accept it.

Here are the declaration and definition statements from C++:

IDL:
[propget, id(6), helpstring("Contains the data returned by the most recent
HTTP request.")] HRESULT Data([out, retval] BSTR* *pVal);

Declaration:
STDMETHOD(get_Data)(/*[out, retval]*/ BSTR* *pVal);

definition:
STDMETHODIMP CHTTP::get_Data(BSTR **pVal)
{
CComBSTR bsData;
bsData = m_sDataReceived.c_str(); //convert string to BSTR
**pVal = bsData.Copy(); //I read on
//
"http://www.roblocher.com/
//
whitepapers/oletypes.aspx"
//that
this was the way to get a
//OLE
compatible BSTR pointer.
//Any
other ideas are welcome.
return S_OK;
}

When compiled, the IDL declaration produces the following warning:

MIDL2039 : interface does not conform to [oleautomation] attribute : [
Parameter 'pVal' of Procedure 'get_Data' ( Interface 'IHTTP' ) ]

It finishes the build process normally, though, without any other errors or
warnings.

When I attempt to use the control on a Visual Basic form (with early
binding), however, I receive the following error if I try to read the Data
property:

"Function or interface marked as restricted, or the function uses an
automation type not supported in Visual Basic."

The Visual Basic object browser lists this property as returning a String,
though, which is what I wanted and expected ... and supposedly is supported
by Visual Basic.

The only difference between this BSTR and the other BSTRings in the
component is that this one is passed as a pointer. I tried changing the
declaration to to eliminate the pointers, but C++ really didn't like that at
all.

There doesn't seem to be much documentation on OLE data type requirements
around, at least not that I've been able to locate. Does anyone know how to
create a BSTR property that Visual Basic will accept?

Thanks,
Ben
Jeremy Boschen
2005-06-14 17:49:18 UTC
Permalink
Post by TxITGuy
Hello,
I am having a curious (and mildly frustrating) problem with a COM component
I am writing in C++. Every method and event works flawlessly in both the
ActiveX Control Test container and in a Visual Basic application. I just
tried to add my first property (get, read-only) to the class, though, and
can't figure out how to get Visual Basic to accept it.
[propget, id(6), helpstring("Contains the data returned by the most recent
HTTP request.")] HRESULT Data([out, retval] BSTR* *pVal);
A BSTR is already typedef'd as an OLECHAR*, so your retval should read:
[out, retval] BSTR* pVal

then ...

STDMETHODIMP CHTTP::get_Data(BSTR **pVal)
{
CComBSTR bsData;
bsData = m_sDataReceived.c_str(); //convert string to BSTR
*pVal = bsData.Copy(); //I read on
...

What you have currently is an OLECHAR***. One too many pointers, which the
MIDL compiler is telling you is not a compatible automation type.

Regards,
Jeremy Boschen
Jeremy Boschen
2005-06-14 17:56:16 UTC
Permalink
Post by TxITGuy
Post by TxITGuy
Hello,
I am having a curious (and mildly frustrating) problem with a COM
component
Post by TxITGuy
I am writing in C++. Every method and event works flawlessly in both the
ActiveX Control Test container and in a Visual Basic application. I just
tried to add my first property (get, read-only) to the class, though, and
can't figure out how to get Visual Basic to accept it.
[propget, id(6), helpstring("Contains the data returned by the most recent
HTTP request.")] HRESULT Data([out, retval] BSTR* *pVal);
[out, retval] BSTR* pVal
then ...
STDMETHODIMP CHTTP::get_Data(BSTR **pVal)
{
CComBSTR bsData;
bsData = m_sDataReceived.c_str(); //convert string to BSTR
*pVal = bsData.Copy(); //I read on
...
opps...
STDMETHODIMP CHTTP::get_Data(BSTR *pVal)
{
...
Kevin Fenters
2005-06-14 17:56:02 UTC
Permalink
A BSTR is defined as: OLECHAR __RPC_FAR *, so what your interface states is
to accept/return a pointer to a pointer to a OLECHAR pointer.

Remove one level of indirection in your MIDL, header and implementation files
and it should work. Not sure what type m_sDataReceived is from your code...
I just usually construct a CComBSTR from a TCHAR array like this.

STDMETHODIMP CZone::get_ZoneName(BSTR *pVal)
{
if (m_pIAreIZon != NULL)
{
CComBSTR bstr(m_pIAreIZon->ZoneIName); // TCHAR Array
*pVal = bstr.Copy();
} else {
CComBSTR bstr;
*pVal = bstr.Copy();
}
return S_OK;
}
Post by TxITGuy
Hello,
I am having a curious (and mildly frustrating) problem with a COM component
I am writing in C++. Every method and event works flawlessly in both the
ActiveX Control Test container and in a Visual Basic application. I just
tried to add my first property (get, read-only) to the class, though, and
can't figure out how to get Visual Basic to accept it.
[propget, id(6), helpstring("Contains the data returned by the most recent
HTTP request.")] HRESULT Data([out, retval] BSTR* *pVal);
STDMETHOD(get_Data)(/*[out, retval]*/ BSTR* *pVal);
STDMETHODIMP CHTTP::get_Data(BSTR **pVal)
{
CComBSTR bsData;
bsData = m_sDataReceived.c_str(); //convert string to BSTR
**pVal = bsData.Copy(); //I read on
//
"http://www.roblocher.com/
//
whitepapers/oletypes.aspx"
//that
this was the way to get a
//OLE
compatible BSTR pointer.
//Any
other ideas are welcome.
return S_OK;
}
MIDL2039 : interface does not conform to [oleautomation] attribute : [
Parameter 'pVal' of Procedure 'get_Data' ( Interface 'IHTTP' ) ]
It finishes the build process normally, though, without any other errors or
warnings.
When I attempt to use the control on a Visual Basic form (with early
binding), however, I receive the following error if I try to read the Data
"Function or interface marked as restricted, or the function uses an
automation type not supported in Visual Basic."
The Visual Basic object browser lists this property as returning a String,
though, which is what I wanted and expected ... and supposedly is supported
by Visual Basic.
The only difference between this BSTR and the other BSTRings in the
component is that this one is passed as a pointer. I tried changing the
declaration to to eliminate the pointers, but C++ really didn't like that at
all.
There doesn't seem to be much documentation on OLE data type requirements
around, at least not that I've been able to locate. Does anyone know how to
create a BSTR property that Visual Basic will accept?
Thanks,
Ben
TxITGuy
2005-06-14 18:18:05 UTC
Permalink
Thanks Jeremy and Kevin.

Kevin, I'll keep the TCHAR suggestion in mind for the future, but I don't
really want to mess with my code that much at this point, since I have it
working.

m_sDataReceived is declared as "string m_sDataReceived;".

I use it as a private global variable to store the document returned from an
HTTP request. Since downloading all the data requires multiple API calls to
InternetReadFile, the append method of the string class lets me put all of
the data into one string without having to worry about runtime memory
allocation.

Ben
Post by Kevin Fenters
A BSTR is defined as: OLECHAR __RPC_FAR *, so what your interface states is
to accept/return a pointer to a pointer to a OLECHAR pointer.
Remove one level of indirection in your MIDL, header and implementation files
and it should work. Not sure what type m_sDataReceived is from your code...
I just usually construct a CComBSTR from a TCHAR array like this.
STDMETHODIMP CZone::get_ZoneName(BSTR *pVal)
{
if (m_pIAreIZon != NULL)
{
CComBSTR bstr(m_pIAreIZon->ZoneIName); // TCHAR Array
*pVal = bstr.Copy();
} else {
CComBSTR bstr;
*pVal = bstr.Copy();
}
return S_OK;
}
Post by TxITGuy
Hello,
I am having a curious (and mildly frustrating) problem with a COM component
I am writing in C++. Every method and event works flawlessly in both the
ActiveX Control Test container and in a Visual Basic application. I just
tried to add my first property (get, read-only) to the class, though, and
can't figure out how to get Visual Basic to accept it.
[propget, id(6), helpstring("Contains the data returned by the most recent
HTTP request.")] HRESULT Data([out, retval] BSTR* *pVal);
STDMETHOD(get_Data)(/*[out, retval]*/ BSTR* *pVal);
STDMETHODIMP CHTTP::get_Data(BSTR **pVal)
{
CComBSTR bsData;
bsData = m_sDataReceived.c_str(); //convert string to BSTR
**pVal = bsData.Copy(); //I read on
//
"http://www.roblocher.com/
//
whitepapers/oletypes.aspx"
//that
this was the way to get a
//OLE
compatible BSTR pointer.
//Any
other ideas are welcome.
return S_OK;
}
MIDL2039 : interface does not conform to [oleautomation] attribute : [
Parameter 'pVal' of Procedure 'get_Data' ( Interface 'IHTTP' ) ]
It finishes the build process normally, though, without any other errors or
warnings.
When I attempt to use the control on a Visual Basic form (with early
binding), however, I receive the following error if I try to read the Data
"Function or interface marked as restricted, or the function uses an
automation type not supported in Visual Basic."
The Visual Basic object browser lists this property as returning a String,
though, which is what I wanted and expected ... and supposedly is supported
by Visual Basic.
The only difference between this BSTR and the other BSTRings in the
component is that this one is passed as a pointer. I tried changing the
declaration to to eliminate the pointers, but C++ really didn't like that at
all.
There doesn't seem to be much documentation on OLE data type requirements
around, at least not that I've been able to locate. Does anyone know how to
create a BSTR property that Visual Basic will accept?
Thanks,
Ben
TxITGuy
2005-06-14 18:00:03 UTC
Permalink
I found the answer at "http://www.codeproject.com/atl/udtdemo.asp". VB
doesn't know what to do with a pointer to a pointer, so the following code
change eliminates the warning and the VB error message.

IDL:
[propget, id(6), helpstring("Contains the data returned by the most recent
HTTP request.")] HRESULT Data([out, retval] BSTR *pVal);

Declaration:
STDMETHOD(get_Data)(/*[out, retval]*/ BSTR *pVal);

definition:
STDMETHODIMP CHTTP::get_Data(BSTR *pVal)
{
CComBSTR bsData;
bsData = m_sDataReceived.c_str(); //convert string to BSTR
*pVal = bsData.Copy(); //get OLE compatible BSTR pointer
//
"http://www.roblocher.com/
//
whitepapers/oletypes.aspx"
return S_OK;
}

Ben

P.S. Anyone want to hazard a guess as to why the ClassWizard creates it as
a pointer to a pointer? Microsoft should know their own technology better
than that.
Loading...