比如函数指针调用,需要有函数原型,传入参数才能使用。 我觉得,函数原型COM不可能提前知道的啊 。如果在编译类型库的时候确定,难道COM的源代码能实现自动编码?

解决方案 »

  1.   

     DISPPARAMS* pdispparams 不就是参数么
      

  2.   

    是参数,解析出参数,调用函数指针,那“函数原型” COM是如何提前预知的?
      

  3.   

    是参数,解析出参数,调用函数指针,那“函数原型” COM是如何提前预知的?
    不需要知道啊,把参数压栈就行了。出错是调用者的问题。
      

  4.   

    Invoke参数说明:
    1. DISPID dispIdMember : 标志客户待调用的函数名,可由GetIDsOfNames获得
    2. REFIID riid : 必须为 IID_NULL
    3. LCID lcid : 用户本地化信息,可用 GetUserDefaultLCID() 获取
    4. WORD wFlags : 一个函数名称其实可以和四个函数关联 (常规函数,设置属性函数,通过引用设置属性函数,获取属性函数),
                     它的值可以是DISPATCH_METHOD, DISPATCH_PROPERTYPUT, DISPATCH_PROPERTYPUTREF, DISPATCH_PROPERTYGET.
    5. DISPPARAMS *pDispParams : 参数列表,其定义如下:[cpp] view plaincopy
    typedef struct tagDISPPARAMS  
        {  
        /* [size_is] */ VARIANTARG *rgvarg; //与VARIANT相同. 所以自动控制程序能支持的类型有限  
        /* [size_is] */ DISPID *rgdispidNamedArgs; //命名参数,C++中不用,VB支持  
        UINT cArgs; //参数个数  
        UINT cNamedArgs;  
        }   DISPPARAMS;  6. VARIANT *pVarResult :保存函数或propget的结果,没有返回值时为NULL
    7. EXCEPINFO *pExcepInfo :保存例外情况的信息,可参考C++异常处理。当Invoke返回DISP_E_EXCEPTION,DISP_E_PARAMNOTFOUND等
                               时,可查询pExcepInfo中相关信息。
      

  5.   

    是参数,解析出参数,调用函数指针,那“函数原型” COM是如何提前预知的?
    不需要知道啊,把参数压栈就行了。出错是调用者的问题。你是说,有这样的API函数么? 不需要函数声明直接压栈的。   或者是,ATL直接使用汇编码搞定的?
      

  6.   

    不使用C代码编译,是不是意味着COM调用的相关部分是汇编码搞定的么? 我很难理解,不需要源码即可调用的机制,能不能介绍一下
      

  7.   

    是参数,解析出参数,调用函数指针,那“函数原型” COM是如何提前预知的?
    不需要知道啊,把参数压栈就行了。出错是调用者的问题。你是说,有这样的API函数么? 不需要函数声明直接压栈的。   或者是,ATL直接使用汇编码搞定的?
    这个实现不在ATL里面内嵌汇编是最简单的实现方式了。
    push ..
    push ..
    call ..
      

  8.   

    是参数,解析出参数,调用函数指针,那“函数原型” COM是如何提前预知的?
    不需要知道啊,把参数压栈就行了。出错是调用者的问题。你是说,有这样的API函数么? 不需要函数声明直接压栈的。   或者是,ATL直接使用汇编码搞定的?
    这个实现不在ATL里面内嵌汇编是最简单的实现方式了。
    push ..
    push ..
    call ..
    多谢
      

  9.   

    微软的一个例子中的 Invoke 实现STDMETHODIMP
    CPoly::Invoke(
                  DISPID dispidMember,
                  REFIID riid,
                  LCID lcid,
                  unsigned short wFlags,
                  DISPPARAMS* pdispparams,
                  VARIANT* pvarResult,
                  EXCEPINFO* pexcepinfo,
                  unsigned int* puArgErr)
    {
      HRESULT hresult;
      VARIANTARG varg0, varg1;
      VARIANT varResultDummy;  UNUSED(lcid);
      UNUSED(pexcepinfo);  if(wFlags & ~(DISPATCH_METHOD | DISPATCH_PROPERTYGET | DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
        return E_INVALIDARG;  // this object only exposes a "default" interface.
      //
      if(!IsEqualIID(riid, IID_NULL))
        return DISP_E_UNKNOWNINTERFACE;  // This makes the following code a bit simpler if the caller
      // happens to be ignoring the return value. Some implementations
      // may choose to deal with this differently.
      //
      if(pvarResult == (VARIANT*)NULL)
        pvarResult = &varResultDummy;  VariantInit(&varg0);
      VariantInit(&varg1);  // assume the return type is void, unless we find otherwise.
      VariantInit(pvarResult);  switch(dispidMember){
        case IDMEMBER_CPOLY_DRAW:
          Draw();
          break;    case IDMEMBER_CPOLY_RESET:
          Reset();
          break;    case IDMEMBER_CPOLY_DUMP:
          Dump();
          break;    case IDMEMBER_CPOLY_QUIT:
          Quit();
          break;    case IDMEMBER_CPOLY_ADDPOINT:
          hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
          if(hresult != NOERROR)
            return hresult;      hresult = DispGetParam(pdispparams, 1, VT_I2, &varg1, puArgErr);
          if(hresult != NOERROR)
            return hresult;      hresult = AddPoint(V_I2(&varg1), V_I2(&varg0));
          if(hresult != NOERROR)
            return hresult;
          break;    case IDMEMBER_CPOLY_ENUMPOINTS:
          IEnumVARIANT* penum;      hresult = EnumPoints(&penum);
          if(hresult != NOERROR)
            return hresult;      V_VT(pvarResult) = VT_UNKNOWN;
          hresult = penum->QueryInterface(
            IID_IUnknown, (void**)&V_UNKNOWN(pvarResult));
          if(hresult != NOERROR)
            return hresult;
          penum->Release();
          break;    case IDMEMBER_CPOLY_GETXORIGIN:
          V_VT(pvarResult) = VT_I2;
          V_I2(pvarResult) = m_xorg;
          break;    case IDMEMBER_CPOLY_SETXORIGIN:
          hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
          if(hresult != NOERROR)
            return hresult;
          m_xorg = V_I2(&varg0);
          break;    case IDMEMBER_CPOLY_GETYORIGIN:
          V_VT(pvarResult) = VT_I2;
          V_I2(pvarResult) = m_yorg;
          break;    case IDMEMBER_CPOLY_SETYORIGIN:
          hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
          if(hresult != NOERROR)
            return hresult;
          m_yorg = V_I2(&varg0);
          break;    case IDMEMBER_CPOLY_GETWIDTH:
          V_VT(pvarResult) = VT_I2;
          V_I2(pvarResult) = GetWidth();
          break;    case IDMEMBER_CPOLY_SETWIDTH:
          hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
          if(hresult != NOERROR)
            return hresult;
          SetWidth(V_I2(&varg0));
          break;    case IDMEMBER_CPOLY_GETRED:
          V_VT(pvarResult) = VT_I2;
          V_I2(pvarResult) = get_red();
          break;    case IDMEMBER_CPOLY_SETRED:
          hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
          if(hresult != NOERROR)
            return hresult;
          set_red(V_I2(&varg0));
          break;    case IDMEMBER_CPOLY_GETGREEN:
          V_VT(pvarResult) = VT_I2;
          V_I2(pvarResult) = get_green();
          break;    case IDMEMBER_CPOLY_SETGREEN:
          hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
          if(hresult != NOERROR)
            return hresult;
          set_green(V_I2(&varg0));
          break;    case IDMEMBER_CPOLY_GETBLUE:
          V_VT(pvarResult) = VT_I2;
          V_I2(pvarResult) = get_blue();
          break;    case IDMEMBER_CPOLY_SETBLUE:
          hresult = DispGetParam(pdispparams, 0, VT_I2, &varg0, puArgErr);
          if(hresult != NOERROR)
            return hresult;
          set_blue(V_I2(&varg0));
          break;    default:
          return DISP_E_MEMBERNOTFOUND;
      }  return NOERROR;
    }
      

  10.   

    是的,这也是我的疑问,上面代码用到的函数都是已知的,然而,我们写的函数原型对COM来说是未知的,这就是问题所在。 所以, 内部用汇编直接压栈比较合理
      

  11.   

    第一个,IDispatch所支持的数据类型是有限的
    第二个,IDispatch的实现需要事先有typelib