invoke方法带回返回值的问题

时间:2022-11-09 00:28:17
invoke方法带回返回值的问题

有多个参数传入,需要传出多个结果,所以考虑到使用传一个指针的方法来实现,当然是in proc的前提下。

type
  ParamRecord=record
    ParamValueArray:array[0..255] of String;
    ParamTypeArray:array[0..255] of Integer;
    ParamCount:Integer;
    ResultValue:String;
    ResultType:Integer;
  end;
  PParamRecord=^ParamRecord;

var
  pr:ParamRecord;  //前面有定义
  //------
  paramcls:TParamCls;//某个类
  HR:HResult;
  MyIntf:IDispatch;
  MyDispParams: TDispParams;
  MyParams: array[0..1] of TVariantArg;
  di:TDispID;
begin
  ......

  HR:=OleContainer1.OleObjectInterface.QueryInterface(myGUID,MyIntf);
  OleCheck(HR);
  // 参数压栈是反序,不过这里只有一个参数,无所谓了。
  MyParams[0].vt := VT_UI4;
  MyParams[0].ulVal := Cardinal(@pr);  //我把指针转成Cardinal,然后在ocx中再用pPR:=Pointer(Value)的方法转回去
  with MyDispParams do
  begin
    rgvarg := @MyParams;
    rgdispidNamedArgs := nil;
    cArgs := 1;
    cNamedArgs := 0;
  end;
  HR:=MyIntf.GetIDsOfNames(GUID_NULL,@Names,1,0,@di);
  OleCheck(HR);
  HR:=MyIntf.Invoke(di,GUID_NULL,0,DISPATCH_METHOD,MyDispParams,nil, nil, nil);  //  (关键位置)
  OleCheck(HR);
  //更新内存变量的值
  paramcls.ParamValue:=pr.ResultValue;

  ......
end;

============================
ocx中的方法的代码

procedure TafxBaseFunc.func_Add(Value: SYSUINT);
var
  pPR:PParamRecord;
  i:Integer;
  fSUM:Double;
begin    //exit; <----
  pPR:=Pointer(Value);
  try
    fSUM:=0;
    for i:=0 to pPR.ParamCount-1 do
    begin
      case pPR.ParamTypeArray[i] of
        VT_UINT,VT_INT,VT_I2,VT_I4,VT_R4,VT_R8:fSUM:=fSUM+StrToFloat(pPR.ParamValueArray[i]);
      end;
    end;
    pPR.ResultValue:=FloatToStr(fSUM);
    pPR.ResultType:=VT_R8;
  except
    pPR.ResultValue:='0';
    pPR.ResultType:=VT_R8;
  end;
end;

经过多个方面的测试,有以下现象和结论:
1。代码能运行,可以得到所需结果,但是平均30秒到1分钟左右,会出现错误,有些错误可以捕捉,有些则直接导致程序关闭;
2。如果把ocx中func_Add的代码屏蔽,即不做运算,则不会有错误出现;

结论:指针访问出现错误。

问题:哪个地方的写法导致了这个错误呢?怎么解决?注:程序中有可能出现临界区的地方都使用了互斥,而且经过检测排除了那种可能。

8 个解决方案

#1


D可以直接创建自动化对象,没必要这么麻烦啊

#2


我现在创建的就是自动化对象啊。我需要在程序中根据方法的名字GetIDsOfNames后去invoke他,请不要跑题。

#3


帮顶

#4


谢谢。

#5


帖子提前太频繁了!真龌龊的提示,我啥时候提前太频繁了?才点了一次而已,真不知道开发程序的程序员怎么设计的。

#6


没人回答。看来,人总要靠自己的。

#7


D作OCX也很简单,没有必要自己去实现Invoke啊

#8


终于有人回复了。感激ing...
不过,问题是这样,假如你有一个系统,可以在系统中集成符合某个标准的ocx插件,并且调用ocx中的函数,那么在系统编译的时候,并不知道ocx提供了什么函数以及函数名是什么,请问,你会怎么实现?

我的方法是通过访问ocx插件的类型库,得到可用函数的列表,然后通过GetIDsOfNames后去Invoke它。

有什么替代的方法么?

#1


D可以直接创建自动化对象,没必要这么麻烦啊

#2


我现在创建的就是自动化对象啊。我需要在程序中根据方法的名字GetIDsOfNames后去invoke他,请不要跑题。

#3


帮顶

#4


谢谢。

#5


帖子提前太频繁了!真龌龊的提示,我啥时候提前太频繁了?才点了一次而已,真不知道开发程序的程序员怎么设计的。

#6


没人回答。看来,人总要靠自己的。

#7


D作OCX也很简单,没有必要自己去实现Invoke啊

#8


终于有人回复了。感激ing...
不过,问题是这样,假如你有一个系统,可以在系统中集成符合某个标准的ocx插件,并且调用ocx中的函数,那么在系统编译的时候,并不知道ocx提供了什么函数以及函数名是什么,请问,你会怎么实现?

我的方法是通过访问ocx插件的类型库,得到可用函数的列表,然后通过GetIDsOfNames后去Invoke它。

有什么替代的方法么?