 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
LarryJ Guest
|
Posted: Fri Mar 16, 2007 3:45 pm Post subject: COM error -2147352571 (80020005) Type mismatch |
|
|
I am trying to make a direct call to the COM function GetAllChartLists(..).
The declaration for this function seen just below if from a type library H
file.
template <class T> HRESULT __fastcall
_cTC2000DispT<T>::GetAllChartLists(LPSAFEARRAY* ChartListNames/*[in,out]*/,
LPSAFEARRAY* ListType/*[in,out]*/)
{
_TDispID _dispid(*this, OLETEXT("GetAllChartLists"), DISPID(1610809350));
TAutoArgs<2> _args;
_args[1] = ChartListNames /*[VT_SAFEARRAY:1]*/;
_args[2] = ListType /*[VT_SAFEARRAY:1]*/;
return OleFunction(_dispid, _args);
}
In my function "My_Call_To_GetAllChartLists( )" I create the COM object,
setup the arrays that I need to pass into the function and start calling the
function like this, TC.Procedure( "GetAllChartLists", args, 2 ). which in
turn calls " Function( name, args, argn, NULL );"
When I finally make the call to the COM object using, hr = idisp->Invoke(
dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &dispparams, rarg,
NULL, &err ); The return value is, -2147352571. This error message is
described on the Microsoft web site as "-2147352571 (80020005) Type
mismatch." I believe this means I am passing the wrong arrays. I don't
know how else to set up the arrays that are passed. Can someone show how to
correctly set this up?
typedef TSafeArrayT<long, VT_I4, 1> TSafeArrayLong1;
typedef TSafeArrayT<BSTR, VT_BSTR, 1> TSafeArrayBSTR1;
void My_Call_To_GetAllChartLists( )
{
long RecCnt=0;
int x=0, i=0;
WideString Name;
VARIANT args[2];
TTC2000 TC;
TC.Create( "TC2000Dev.cTC2000" );
//++++++++++ Setup Arrays ++++++++
TSafeArrayDim1 DimChartListNames(0);
TSafeArrayDim1 DimListType(0);
TSafeArrayBSTR1 ChartListNames ( DimChartListNames );
TSafeArrayInt1 ListType( DimListType );
args[0].vt = VT_BSTR;
args[1].vt = VT_R4;
args[0].pparray = &(ChartListNames);
args[1].pparray = &(ListType);
//++++++++++++++++++++++++++++++++
//++++CALL FUNCTION+++++
if( TC.Procedure( "GetAllChartLists", args, 2 ) ) {
RecCnt = ChartListNames.BoundsLength[0];
//Test The Return Values
for(i=1; i<RecCnt+1; i++){
Name = ChartListNames[i];
}
}
return;
}
//------------------------------------------------------------
bool TOleAuto::Procedure( const char* name, VARIANT* args, unsigned int
argn ) {
return Function( name, args, argn, NULL );
}
//------------------------------------------------------------
bool TOleAuto::Function( const char* name,
VARIANT* args, unsigned int argn, VARIANT* rarg) {
DISPID dispid;
if( GetIDsOfNames( name, dispid ) ) {
dispparams.rgvarg = args;
dispparams.cArgs = argn;
hr = idisp->Invoke( dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, &dispparams, rarg, NULL, &err );
}
return hr == 0;
}
//------------------------------------------------------------
bool TOleAuto::GetIDsOfNames( const char* name, DISPID& iid ) {
hr = idisp->GetIDsOfNames( IID_NULL, &WideString( name ), 1,
LOCALE_SYSTEM_DEFAULT, &iid );
return hr == 0;
}
//------------------------------------------------------------
Thanks
Larry Johnson. |
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Fri Mar 16, 2007 10:34 pm Post subject: Re: COM error -2147352571 (80020005) Type mismatch |
|
|
"LarryJ" <LarryJ33 (AT) austin (DOT) rr.com> wrote in message
news:45fa7544$1 (AT) newsgroups (DOT) borland.com...
| Quote: | In my function "My_Call_To_GetAllChartLists( )" I create the
COM object, setup the arrays that I need to pass into the function
and start calling the function like this,
TC.Procedure( "GetAllChartLists", args, 2 ).
|
Why are you not calling the wrapper function that you showed?
LPSAFEARRAY ChartListNames, ListType;
// initialize arrays as needed, then...
hRes = TC.GetAllChartLists(&ChartListNames, &ListType);
| Quote: | When I finally make the call to the COM object using,
hr = idisp->Invoke(...); The return value is, -2147352571.
|
That is DISP_E_TYPEMISMATCH:
"One or more of the arguments could not be coerced. The index
within rgvarg of the first parameter with the incorrect type is
returned in the puArgErr parameter."
The parameters being passed in to Invoke() are not set up correctly
for the COM method you are trying to call. Since you are ignoring the
wrapper function and calling Procedure() directly, the mismatch is in
your own code, because you are not passing the arrays correctly at
all.
| Quote: | I believe this means I am passing the wrong arrays. I don't
know how else to set up the arrays that are passed. Can
someone show how to correctly set this up?
|
You could start by not calling Procedure() directly in the first
place. Let the wrapper class do the work for you.
| Quote: | args[0].vt = VT_BSTR;
args[1].vt = VT_R4;
|
That is completely wrong. You are telling the method that you are
passing in a single string and a single float (which you are really
not), but the COM method is expecting you to pass in pointers to array
pointers instead (which you are doing, but not telling the method
that). The arrays themselves specify the data types that they hold.
You do not specify the array types in the VARIANTs that are being
passed to the method. You need to use the VT_ARRAY and VT_BYREF flags
instead, ie:
args[0].vt = VT_ARRAY | VT_BYREF;
args[1].vt = VT_ARRAY | VT_BYREF;
Gambit |
|
| Back to top |
|
 |
LarryJ Guest
|
Posted: Sat Mar 17, 2007 3:56 am Post subject: Re: COM error -2147352571 (80020005) Type mismatch |
|
|
I have the wrapper setup and it works fine. Unfortunately the program I link
to changes the GUID each time they release a new build. This means my
program's COM link is dead every time they release a new build. I have two
chooses, 1) I can build my COM link into a DLL so I only need to distribute
a new DLL or 2) I can create the COM object dynamically and call the COM
functions directly. I am trying to setup option #2 but I have only been able
to get 1 of 3 functions working. Below is the GetPrices function from the
type library and the way I setup the call. This seems to work. But the
function shown in the previous post GetAllChartLists( ) I can't get to work.
For the function GetAllChartLists( ) I tried these two setups for args[0]
and args[1]. They both return the same -2147352571 error. Any advice for
getting the function GetAllChartLists( ) working would really help. Thanks
Larry Johnson.
args[0].vt = VT_ARRAY | VT_BYREF;
args[1].vt = VT_ARRAY | VT_BYREF;
args[0].vt = VT_BSTR | VT_ARRAY | VT_BYREF;
args[1].vt = VT_I4 | VT_ARRAY | VT_BYREF;
template <class T> HRESULT __fastcall
_cTC2000DispT<T>::GetPrices(long* WordenNum/*[in,out]*/, LPSAFEARRAY*
OpenPrices/*[in,out]*/,
LPSAFEARRAY* HighPrices/*[in,out]*/,
LPSAFEARRAY* LowPrices/*[in,out]*/
, LPSAFEARRAY* ClosePrices/*[in,out]*/,
LPSAFEARRAY* Volumes/*[in,out]*/
, LPSAFEARRAY* Dates/*[in,out]*/, long*
NumberOfPricesToGet/*[in,out]*/)
{
_TDispID _dispid(*this, OLETEXT("GetPrices"), DISPID(1610809365));
TAutoArgs<8> _args;
_args[1] = WordenNum /*[VT_I4:1]*/;
_args[2] = OpenPrices /*[VT_SAFEARRAY:1]*/;
_args[3] = HighPrices /*[VT_SAFEARRAY:1]*/;
_args[4] = LowPrices /*[VT_SAFEARRAY:1]*/;
_args[5] = ClosePrices /*[VT_SAFEARRAY:1]*/;
_args[6] = Volumes /*[VT_SAFEARRAY:1]*/;
_args[7] = Dates /*[VT_SAFEARRAY:1]*/;
_args[8] = NumberOfPricesToGet /*[VT_I4:1]*/;
return OleFunction(_dispid, _args);
}
typedef TSafeArrayT<float, VT_R4, 1> TSafeArrayFloat1;
typedef TSafeArrayFloat1 TPrice;
int MY_GetPrices( )
{
AnsiString Symb;
int date2=1, vol2=1, GetRec=0, Wnum=0, i=0;
unsigned long RecCnt;
VARIANT rarg, args[8];
float open2=1, high2=1, low2=1, close2=1;
TC.Create( "TC2000Dev.cTC2000" );
Symb = "IBM";
Wnum = 15;
GetRec = 252;
TAutoArgs<0> _args;
TOLEBOOL bbEnabled;
rarg.vt = VT_BOOL | VT_BYREF;
args[0].vt = VT_BOOL | VT_BYREF;
args[0].vt = VT_BSTR;
args[0].bstrVal = WideString( "IBM" );
rarg.vt = VT_I4;
TSafeArrayDim1 DimOpen(0);
TSafeArrayDim1 DimHigh(0);
TSafeArrayDim1 DimLow(0);
TSafeArrayDim1 DimClose(0);
TSafeArrayDim1 DimVolume(0);
TSafeArrayDim1 DimDate(0);
TPrice Open ( DimOpen );
TPrice High ( DimHigh );
TPrice Low ( DimLow );
TPrice Close( DimClose );
TSafeArrayInt1 Volume( DimVolume );
TSafeArrayInt1 Date ( DimDate );
args[7].vt = VT_I4;
args[7].lVal = Wnum;
args[6].vt = args[5].vt =
args[4].vt = args[3].vt = VT_R4 | VT_ARRAY | VT_BYREF;
args[2].vt = args[1].vt = VT_I4 | VT_ARRAY | VT_BYREF;
args[6].pparray = &(Open);
args[5].pparray = &(High);
args[4].pparray = &(Low);
args[3].pparray = &(Close);
args[2].pparray = &(Volume);
args[1].pparray = &(Date);
args[0].vt = VT_I4;
args[0].lVal = GetRec;
if( TC.Procedure( "GetPrices", args, 8 ) ) {
RecCnt = Date.BoundsLength[0];
//Check Values
for(i=1; i<RecCnt+1; i++){
date2 = Date[i];
open2 = Open[i];
high2 = High[i];
low2 = Low[i];
close2 = Close[i];
vol2 = Volume[i];
}
}else {
return(-1);
}
return(0);
}
//----------------------------------------------------------------------------
"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote in message
news:45fac759$1 (AT) newsgroups (DOT) borland.com...
> |
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Sat Mar 17, 2007 6:07 am Post subject: Re: COM error -2147352571 (80020005) Type mismatch |
|
|
"LarryJ" <LarryJ33 (AT) austin (DOT) rr.com> wrote in message
news:45fb20ce$1 (AT) newsgroups (DOT) borland.com...
| Quote: | I have the wrapper setup and it works fine. Unfortunately the
program I link to changes the GUID each time they release a new
build. |
We already talked about that in another discussion. That has nothing
to do with the topic at hand now.
| Quote: | For the function GetAllChartLists( ) I tried these two setups for
args[0] and args[1]. They both return the same -2147352571 error.
|
Then your safearrays themselves are likely using the wrong data types
to begin with. What EXACTLY does GetAllChartLists() expect you to
pass in? What EXACTLY does it return? What EXACTLY does its
documentation say?
| Quote: | args[0].bstrVal = WideString( "IBM" );
|
That is a crash waiting to happen. The WideString is temporary. It
will be freed when it gos out of scope. The BSTR that it allocates
will be freed immediately, leaving your VARIANT holding on to an
invalid pointer.
| Quote: | if( TC.Procedure( "GetPrices", args, 8 ) ) {
|
As I told you earlier, you do not need to call Procedure() directly,
especially since you are not even setting up the arguments correctly
to begin with. The wrapper class already implements adequate methods
that handle all of that stuff for you. You should be using them, ie:
int MY_GetPrices( )
{
TC.Create( "TC2000Dev.cTC2000" );
if( TC )
{
TSafeArrayDim1 DimOpen(0);
TPrice Open(DimOpen);
TSafeArrayDim1 DimHigh(0);
TPrice High(DimHigh);
TSafeArrayDim1 DimLow(0);
TPrice Low(DimLow);
TSafeArrayDim1 DimClose(0);
TPrice Close(DimClose);
TSafeArrayDim1 DimVolume(0);
TSafeArrayInt1 Volume(DimVolume);
TSafeArrayDim1 DimDate(0);
TSafeArrayInt1 Date(DimDate);
long Wnum = 15;
long GetRec = 252;
TC.GetPrices(&Wnum, &Open, &High, &Low, &Close, &Volume,
&Date, &GetRec);
unsigned int RecCnt = Date.BoundsLength[0];
for(unsigned int i = 1; i < RecCnt+1; ++i)
{
//...
}
}
return 0;
}
Now, with that said, you haven't shown what your latest code that is
failing for GetAllChartLists() looks like.
Gambit |
|
| Back to top |
|
 |
LarryJ Guest
|
Posted: Sat Mar 17, 2007 7:01 am Post subject: Re: COM error -2147352571 (80020005) Type mismatch |
|
|
Gambit,
At the bottom of the post I show all the information about how I am calling
GetAllChartLists( ) through Procedure().
What you posted makes me believe I am creating the COM object wrong. Let me
explain how I am doing that.
I created a Class named "class TOleAuto" that is shown below. In this class
I add the functions I can call such as Create(), Procedure(), Function(),
GetIDsOfNames(). The 2 Create functions are shown below. When I create the
COM object this way I do not have access to all the wrapper functions and
the wrapper H files are not even included in the project. I then call all
the COM functions using the Procedure() and Function() seen previously. This
seemed to be the only way I could get around using the hard coded GUID that
changes. If I try to call TC.GetPrices(&Wnum, &Open, &High, &Low, &Close,
&Volume, &Date, &GetRec); I will get the error "'GetPrices' is not a member
of TTC2000". Am I creating this COM object wrong?
TTC2000 TC;
TC.Create( "TC2000Dev.cTC2000" );
bool TOleAuto::Create( char* pszName ) {
bool bSuccess = true;
try {
iid = ProgIDToClassID( WideString( pszName ) );
}
catch ( const EOleSysError& ) { bSuccess = false; }
if ( bSuccess )
bSuccess = Create( iid );
return bSuccess;
}
//------------------------------------------------------------
bool TOleAuto::Create( GUID IID ) {
bool bResult = ( IID != GUID_NULL );
if( bResult ) {
iid = IID;
hr = CoCreateInstance( iid, NULL, CLSCTX_SERVER,
IID_IDispatch, (LPVOID*) &idisp );
bResult = ( hr == 0 );
}
return bResult;
}
//------------------------------------------------------------
// Simple modular Ole automation wrapper
class TOleAuto {
public:
TOleAuto() : idisp( NULL ), iid( GUID_NULL ) { init(); }
TOleAuto( IDispatch* iptr ) : idisp( iptr ) { init(); }
void init() { dispparams.rgdispidNamedArgs = NULL;
dispparams.cNamedArgs = 0;
TInitOle::Init(); }
bool isBound() const {return idisp != NULL;}
GUID GetID() { return iid; }
IDispatch* GetDispIntf() { return idisp; }
bool Create( char* pszName );
bool Create( GUID iid );
bool GetIDsOfNames( const char* name, DISPID& dispid );
bool Procedure( const char* name, VARIANT* args, unsigned int argn );
bool Procedure( DISPID& dispid, VARIANT* args, unsigned int argn );
bool Function ( const char* name, VARIANT* args, unsigned argn, VARIANT*
rarg );
bool Function ( DISPID& dispid, VARIANT* args, unsigned argn, VARIANT*
rarg );
bool Function ( DISPID& dispid, TAutoArgsBase& args );
IDispatch* GetIDisp() { return idisp; }
private:
HRESULT hr;
GUID iid;
IDispatch* idisp;
DISPPARAMS dispparams;
unsigned int err;
};
\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Here are all the references to the function GetAllChartLists() in the type
library file
//-----------------------------------------------------
virtual HRESULT STDMETHODCALLTYPE GetAllChartLists(LPSAFEARRAY*
ChartListNames/*[in,out]*/,
LPSAFEARRAY*
ListType/*[in,out]*/) = 0; // [1610809350]
//-----------------------------------------------------
HRESULT __fastcall GetAllChartLists(LPSAFEARRAY*
ChartListNames/*[in,out]*/,
LPSAFEARRAY*
ListType/*[in,out]*/);
//-----------------------------------------------------
HRESULT __fastcall GetAllChartLists(LPSAFEARRAY*
ChartListNames/*[in,out]*/,
LPSAFEARRAY*
ListType/*[in,out]*/);
//-----------------------------------------------------
//I believe TCOM_cTC2000 is the object whos GUID changes each build.
template <class T> HRESULT __fastcall
TCOM_cTC2000T<T>::GetAllChartLists(LPSAFEARRAY* ChartListNames/*[in,out]*/,
LPSAFEARRAY* ListType/*[in,out]*/)
{
return (*this)->GetAllChartLists(ChartListNames, ListType);
}
//-----------------------------------------------------
template <class T> HRESULT __fastcall
_cTC2000DispT<T>::GetAllChartLists(LPSAFEARRAY* ChartListNames/*[in,out]*/,
LPSAFEARRAY* ListType/*[in,out]*/)
{
_TDispID _dispid(*this, OLETEXT("GetAllChartLists"), DISPID(1610809350));
TAutoArgs<2> _args;
_args[1] = ChartListNames /*[VT_SAFEARRAY:1]*/;
_args[2] = ListType /*[VT_SAFEARRAY:1]*/;
return OleFunction(_dispid, _args);
}
//-----------------------------------------------------
//+++++++++In my H file+++++++++
typedef TSafeArrayT<long, VT_I4, 1> TSafeArrayLong1;
typedef TSafeArrayT<BSTR, VT_BSTR, 1> TSafeArrayBSTR1;
typedef TSafeArrayT<float, VT_R4, 1> TSafeArrayFloat1;
class TTC2000 : public TOleAuto {
};
//++++++In My CPP file+++++++++
TTC2000 TC
void My_Call_To_GetAllChartLists( )
{
long RecCnt=0;
int x=0, i=0;
WideString Name;
VARIANT rarg, args[2];
TAutoArgs<0> _args;
TOLEBOOL bbEnabled;
rarg.vt = VT_BOOL | VT_BYREF;
TC.Create( "TC2000Dev.cTC2000" );
TSafeArrayDim1 DimChartListNames(0);
TSafeArrayDim1 DimListType(0);
TSafeArrayBSTR1 ChartListNames ( DimChartListNames );
TSafeArrayLong1 ListType( DimListType );
// args[0].vt = VT_ARRAY | VT_BYREF;
// args[1].vt = VT_ARRAY | VT_BYREF;
args[0].vt = VT_BSTR | VT_ARRAY | VT_BYREF;
args[1].vt = VT_I4 | VT_ARRAY | VT_BYREF;
args[0].pparray = &(ChartListNames);
args[1].pparray = &(ListType);
if( TC.Procedure( "GetAllChartLists", args, 2 ) ) {
RecCnt = ChartListNames.BoundsLength[0];
//Test The Return Values
for(i=1; i<RecCnt+1; i++){
Name = ChartListNames[i];
}
}
return;
}
//------------------------------------------------------------------------ |
|
| Back to top |
|
 |
Remy Lebeau (TeamB) Guest
|
Posted: Sat Mar 17, 2007 8:10 am Post subject: Re: COM error -2147352571 (80020005) Type mismatch |
|
|
"LarryJ" <LarryJ33 (AT) austin (DOT) rr.com> wrote in message
news:45fb4bf3$1 (AT) newsgroups (DOT) borland.com...
| Quote: | At the bottom of the post I show all the information about how
I am calling GetAllChartLists( ) through Procedure().
|
Which you are still setting up wrong. Why are you still using
Procedure()? You are not using it correctly.
| Quote: | What you posted makes me believe I am creating the COM object wrong.
|
No, you are not. You are just not setting up the parameters correctly
when calling into it. I've explained to you several times now how to
use it correctly, but you are not using what I have shown you.
| Quote: | Let me explain how I am doing that.
|
There is no explanation needed. There is only one way to create an
instance of a COM object. It either succeeds or fails. There is no
in-between.
| Quote: | I created a Class named "class TOleAuto" that is shown below.
|
There was no need to do that. The TLB wrapper already handles
IDispatch for you. You are duplicating functionality that was already
available to you from the very beginning.
| Quote: | I then call all the COM functions using the Procedure()
and Function() seen previously.
|
And you are doing so completely wrong, for reasons I have already
pointed out to you. You are not setting up the arguments properly.
| Quote: | This seemed to be the only way I could get around using the
hard coded GUID that changes.
|
That is not true. You could have use the TLB wrapper just fine
without using the GUID at all. I explained to you a week ago how to
do that. Look back at the "COM Upgrade and back compatibility"
discussion. You never replied to it.
| Quote: | If I try to call TC.GetPrices(...); I will get the error
"'GetPrices' is not a member of TTC2000".
|
That is because you did not add any methods to TTC2000. You never
said that you were writing your own classes. This whole time, I
thought you were using the TLB wrapper as-is. You should have made
that clearer earlier. Why are you not using the TLB wrapper as-is?
It will work fine, if you will just use it correctly in the first
place.
| Quote: | I believe TCOM_cTC2000 is the object whos GUID changes each build.
|
That is irrelevant now. TCOM_cTC2000T is a wrapper for an interface
pointer, regardless of whether that pointer is instantiated via a GUID
or a ProgID. Use TCOM_cTC2000T as-is. It will work for you.
TOleAuto is wasting your time and efforts, until you get a better
unstanding of how to work with IDispatch::Invoke() arguments properly.
--- Cpp ---
TCOM_cTC2000 TC;
void My_Call_To_GetAllChartLists()
{
if( !TC )
TC.CreateInstance(L"TC2000Dev.cTC2000");
if( TC )
{
TSafeArrayDim1 EmptyDim(0);
TSafeArrayBSTR1 ChartListNames(EmptyDim);
TSafeArrayLong1 ListType(EmptyDim);
if( SUCCEEDED(TC->GetAllChartLists(&ChartListNames,
&ListType)) )
{
//...
}
}
}
void My_Call_To_GetPrices()
{
if( !TC )
TC.CreateInstance(L"TC2000Dev.cTC2000");
if( TC )
{
TSafeArrayDim1 EmptyDim(0);
TPrice Open(EmptyDim);
TPrice High(EmptyDim);
TPrice Low(EmptyDim);
TPrice Close(EmptyDim);
TSafeArrayInt1 Volume(EmptyDim);
TSafeArrayInt1 Date(EmptyDim);
long Wnum = 15;
long GetRec = 252;
if( SUCCEEDED(TC->GetPrices(&Wnum, &Open, &High, &Low,
&Close, &Volume, &Date, &GetRec)) )
{
//...
}
}
}
Gambit |
|
| Back to top |
|
 |
LarryJ Guest
|
Posted: Sun Mar 18, 2007 8:47 pm Post subject: Re: COM error -2147352571 (80020005) Type mismatch |
|
|
I got this COM setup working. Thank you very much for your help.
Larry.
"Remy Lebeau (TeamB)" <no.spam (AT) no (DOT) spam.com> wrote in message |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|