OLE - Call
-
ich habe irgendwie Probleme mit Funktionaufrufen von OLE-Ojekten.
Zum Aufruf erwartet das OLE-Objekt eine Parameterliste - aber in umgekehrter Reihenfolge. Wenn ich jetzt die Parameter aus einem normalen Funktionsaufruf an ein OLE-Objekt weitergeben muß, muß ich die Reihenfolge der Parameter umkehren.Beispiel:
long Connections::Add(const VARIANT FAR& ServerName, const VARIANT FAR& DatabaseName, const VARIANT FAR& UserName, const VARIANT FAR& Password) { USES_CONVERSION; UINT Pos; VARIANT here; OLECHAR FAR* method = A2OLE("Connect"); // OLE-Methode VARIANT args[4]; DISPPARAMS param; //der Parameterblock DISPID dispid; args[0]=Password; // hier wird die Reihenfolge umgekehrt args[1]=UserName; args[2]=DatabaseName; args[3]=ServerName; params.rgvarg=args; params.cArgs=4; params.cNamedArgs=0; Pos=AddToCollection(new IConnection*,vConnections, CLSID_Connection, DIID_IConnection); (*vConnections.at(Pos))->GetIDsOfNames(IID_NULL,&method,1,LOCALE_USER_DEFAULT, &dispid); (*vConnections.at(Pos))->Invoke(dispid,IID_NULL,LOCALE_USER_DEFAULT,DISPATCH_METHOD,¶ms,&here,NULL,NULL); return Pos; }
Mir war es viel zu blöd, das jedesmal zu schreiben, deshalb habe ich ein Template erstellt, das mir das abnimmt.
template <class T> VARIANT OleCall(T& OLE, // IDispatch* char* cmd, // name of invoked method const COleVariant& v0=Empty(COleVariant()), //parameters; Empty() sets VARIANT to VT_EMPTY const COleVariant& v1=Empty(COleVariant()), const COleVariant& v2=Empty(COleVariant()), const COleVariant& v3=Empty(COleVariant()), const COleVariant& v4=Empty(COleVariant()), const COleVariant& v5=Empty(COleVariant()), const COleVariant& v6=Empty(COleVariant()), const COleVariant& v7=Empty(COleVariant())) { USES_CONVERSION; int i=0,j=0; COleVariant args[8]; DISPPARAMS params; DISPID dispid; OLECHAR FAR* method; VARIANT result; args[0]=v7; args[1]=v6; args[2]=v5; args[3]=v4; args[4]=v3; args[5]=v2; args[6]=v1; args[7]=v0; while ((args[0].vt==VT_EMPTY) && (j<8)) { for (i=0;i<7;++i) { args[i]=args[i+1]; } j+=1; Empty(args[8-j]); } params.rgvarg=args; params.cArgs=8-j; params.cNamedArgs=0; method=A2OLE(cmd); OLE->GetIDsOfNames(IID_NULL,&method,1,LOCALE_SYSTEM_DEFAULT, &dispid); OLE->Invoke(dispid,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_METHOD,¶ms,&result,NULL,NULL); return result; }
Das funktionert soweit auch, der Funktionsaufruf von oben reduziert sich auf:
long Connections::Add(const VARIANT FAR& ServerName, const VARIANT FAR& DatabaseName, const VARIANT FAR& UserName, const VARIANT FAR& Password) { UINT Pos; Pos=AddToCollection(new IConnection*,vConnections, CLSID_Connection, DIID_IConnection); OleCall(*vConnections.at(Pos),"Connect",ServerName,DatabaseName,UserName,Password); return Pos; }
Nur: irgendwie erscheint mir das denn doch "Pfusch" zu sein - es muß doch eine elegantere Methode für OLE-Aufrufe geben - wie macht ihr das?
P.S: irgendwie wird hier automatisch "& p a r a m s" durch "¶ms" ersetzt *grübel* also im Originaltext steht "& p a r a m s" (ohne Leerzeichen)
[ Dieser Beitrag wurde am 14.03.2003 um 16:41 Uhr von CodeWalker editiert. ]
-
Benutz doch ne variable Argumentenliste statt '8'. Aber kürzer wirds dadurch auch nicht
[ Dieser Beitrag wurde am 14.03.2003 um 17:03 Uhr von RenéG editiert. ]
-
Was ist das für ein Aufruf:
Pos=AddToCollection(new IConnection*,vConnections, CLSID_Connection, DIID_IConnection);
Speziell 'new IConnection*' versteh ich net so ganz.
-
Ich hab das nur schnell mal so hingepfuscht, weil mir nix besseres eingefallen ist. Aber mir gefällt das Ganze prinzipiell nicht. Kann doch nicht sein, daß man für einen simplen Methodenaufruf so ein Konstrukt braucht - oder doch?
-
@Rene:
Pos=AddToCollection(new IConnection*,vConnections, CLSID_Connection, DIID_IConnection);=> spielt hier vom Prinzip her keine Rolle, kommt aus dem Kontext
IConnection* ist ein Pointer auf ein IDispatch-Interface-Pointer (IDispatch**)
template<class T, class V> long AddToCollection(T& t, std::vector<V>& vV, CLSID clsid, IID diid) { HRESULT error=NULL; std::vector<V>::iterator VPos; VPos=vV.insert(vV.end(),t); error=CoCreateInstance(clsid,NULL,CLSCTX_ALL,diid,(VOID**)*VPos); assert(error==0); return VPos-vV.begin(); }
[ Dieser Beitrag wurde am 14.03.2003 um 17:22 Uhr von CodeWalker editiert. ]