F
fly_123
Unregistered / Unconfirmed
GUEST, unregistred user!
我想使用IDispatch的后期绑定技术,即通过传入组件的ClsID,方法的名字,方法的参数集,得到我想要的结果,即使用invoke方法。
对于参数都是const的,我没有问题,现在的问题是,我的组件的很多方法的参数都是var型和out型的,我希望调用时把这些也传出来,请问如何处理?
下面是我写的代码的关键部分,大家看看有什么问题?
procedure TdmSocket.InvokeCall(const AstrClsID, AstrMethodID: WideString;
var AvarParams, AvarResult: OleVariant);
//上面的参数的含义依次是:组件的ClsID,方法的名字,参数数组,结果集数组
procedure GetArgsFromParams( var Args : array of TVariantArg );
//把AvarParams即传入的参数组合传递到TDispParams中去,以备invoke调用
var
lIndex, lHigh : integer ;
varValue : oleVariant ;
begin
lhigh := VarArrayHighBound( AvarParams, 1 );
for lIndex := 0 to lhighdo
begin
varValue := AvarParams[lIndex];
if VarType( varValue ) = varInteger then
begin
Args[lHigh - lIndex].vt := VT_I4;
Args[lHigh - lIndex].lVal := StrToInt( VarToStr( varValue ));
end
else
if ( VarType( varValue ) = varString ) or
( VarType( varValue ) = varOleStr ) then
begin
Args[lHigh - lIndex].vt := VT_BSTR;
Args[lHigh - lIndex].bstrVal := PWideChar( WideString( VarToStr( varValue ) ));
end ;
end ;
end ;
procedure GetParamsFromArgs( disParams : TDispParams );
//把TDispParams型的参数传回到AvarParams,以便传回给客户端
var
lIndex, lHigh, pArgErr : integer ;
varValue, var2 : oleVariant ;
begin
lhigh := VarArrayHighBound( AvarParams, 1 );
for lIndex := 0 to lhighdo
begin
varValue := AvarParams[lIndex];
DispGetParam( disParams, lHigh-lIndex, VT_BSTR, var2, pArgErr);
if var2 <> varValue then
begin
AvarParams[lIndex] := var2 ;
end ;
end ;
end ;
var
objUnknown : IDispatch ;
Names : array [0..0] of PWideChar;
disps : array [0..0] of TDispID;
varParams : TDispParams ;
ReturnValue : OleVariant;
arrArgs: array[0..1000] of TVariantArg ;
lRet, lhigh : integer ;
aexception: TExcepInfo;
begin
objUnknown := CreateComobject( StringToGuid( AstrClsID) ) as IDispatch;
Names[0] := StringToOleStr( AstrMethodID );
objUnknown.GetIDsOfNames( GUID_NULL, @Names, 1, LOCALE_SYSTEM_DEFAULT, @disps );
lhigh := VarArrayHighBound( AvarParams, 1 );
GetArgsFromParams( arrArgs );
varParams.rgvarg := @arrArgs ;
varParams.rgdispidNamedArgs := nil;
varParams.cNamedArgs := 0;
varParams.cArgs := lHigh + 1;
lRet := objUnknown.Invoke( disps[0], GUID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, varParams, @ReturnValue, @aexception, nil );
if lRet <> 0 then
begin
raise Exception.Create( IntToStr( lRet ) + ';' +
String( aexception.bstrSource ) );
end
else
begin
AvarResult := ReturnValue;
GetParamsFromArgs( varParams );
end ;
end;
在有var或out型参数的时候就会报错
对于参数都是const的,我没有问题,现在的问题是,我的组件的很多方法的参数都是var型和out型的,我希望调用时把这些也传出来,请问如何处理?
下面是我写的代码的关键部分,大家看看有什么问题?
procedure TdmSocket.InvokeCall(const AstrClsID, AstrMethodID: WideString;
var AvarParams, AvarResult: OleVariant);
//上面的参数的含义依次是:组件的ClsID,方法的名字,参数数组,结果集数组
procedure GetArgsFromParams( var Args : array of TVariantArg );
//把AvarParams即传入的参数组合传递到TDispParams中去,以备invoke调用
var
lIndex, lHigh : integer ;
varValue : oleVariant ;
begin
lhigh := VarArrayHighBound( AvarParams, 1 );
for lIndex := 0 to lhighdo
begin
varValue := AvarParams[lIndex];
if VarType( varValue ) = varInteger then
begin
Args[lHigh - lIndex].vt := VT_I4;
Args[lHigh - lIndex].lVal := StrToInt( VarToStr( varValue ));
end
else
if ( VarType( varValue ) = varString ) or
( VarType( varValue ) = varOleStr ) then
begin
Args[lHigh - lIndex].vt := VT_BSTR;
Args[lHigh - lIndex].bstrVal := PWideChar( WideString( VarToStr( varValue ) ));
end ;
end ;
end ;
procedure GetParamsFromArgs( disParams : TDispParams );
//把TDispParams型的参数传回到AvarParams,以便传回给客户端
var
lIndex, lHigh, pArgErr : integer ;
varValue, var2 : oleVariant ;
begin
lhigh := VarArrayHighBound( AvarParams, 1 );
for lIndex := 0 to lhighdo
begin
varValue := AvarParams[lIndex];
DispGetParam( disParams, lHigh-lIndex, VT_BSTR, var2, pArgErr);
if var2 <> varValue then
begin
AvarParams[lIndex] := var2 ;
end ;
end ;
end ;
var
objUnknown : IDispatch ;
Names : array [0..0] of PWideChar;
disps : array [0..0] of TDispID;
varParams : TDispParams ;
ReturnValue : OleVariant;
arrArgs: array[0..1000] of TVariantArg ;
lRet, lhigh : integer ;
aexception: TExcepInfo;
begin
objUnknown := CreateComobject( StringToGuid( AstrClsID) ) as IDispatch;
Names[0] := StringToOleStr( AstrMethodID );
objUnknown.GetIDsOfNames( GUID_NULL, @Names, 1, LOCALE_SYSTEM_DEFAULT, @disps );
lhigh := VarArrayHighBound( AvarParams, 1 );
GetArgsFromParams( arrArgs );
varParams.rgvarg := @arrArgs ;
varParams.rgdispidNamedArgs := nil;
varParams.cNamedArgs := 0;
varParams.cArgs := lHigh + 1;
lRet := objUnknown.Invoke( disps[0], GUID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, varParams, @ReturnValue, @aexception, nil );
if lRet <> 0 then
begin
raise Exception.Create( IntToStr( lRet ) + ';' +
String( aexception.bstrSource ) );
end
else
begin
AvarResult := ReturnValue;
GetParamsFromArgs( varParams );
end ;
end;
在有var或out型参数的时候就会报错