How does CreateStdDispatch know what method to inv

2019-04-10 03:41发布

i'm faced with implementing an IDispatch interface. There are four methods, and fortunately 3 of them are easy:

function TIEEventsSink.GetTypeInfoCount(...): HResult;
{
   Result := E_NOTIMPL;
}

function TIEEventsSink.GetTypeInfo(...): HResult;
{
   Result := E_NOTIMPL;
}

function TIEEventsSink.GetIDsOfNames(...): HResult;
{
   Result := E_NOTIMPL;
}

It's the last method, Invoke that is difficult. Here i am faced with having to actually case the DispID, and call my appropriate method; unmarhsalling parameters from a variant array.

function Invoke(  
  dispIdMember: DISPID;
  riid: REFIID;
  lcid: LCID;
  wFlags: WORD;
  var pDispParams: DISPPARAMS;
  var pVarResult: VARIANT;
  var pExcepInfo: EXCEPINFO;
  var puArgErr: DWORD
): HRESULT;

Not wanting to have to write all the tedious boilerplate code, that i'm sure will have bugs, i went googling - rather than doing any work.

i found this snippit on the MSDN Documentation of IDispatch.Invoke:

Generally, you should not implement Invoke directly.

Excellent! i didn't want to implement it anyway! Continuing reading:

Instead, use the dispatch interface to create functions CreateStdDispatch and DispInvoke. For details, refer to CreateStdDispatch, DispInvoke, Creating the IDispatch Interface and Exposing ActiveX Objects.

The Creating the IDispatch Interface link says:

You can implement IDispatch by any of the following means:

  • [snip]
  • Calling the CreateStdDispatch function. This approach is the simplest, but it does not provide for rich error handling or multiple national languages.
  • [snip]

Excellent, CreateStdDispatch it is:

Creates a standard implementation of the IDispatch interface through a single function call. This simplifies exposing objects through Automation.

HRESULT CreateStdDispatch(  
  IUnknown FAR*  punkOuter,        
  void FAR*  pvThis,               
  ITypeInfo FAR*  ptinfo,          
  IUnknown FAR* FAR* ppunkStdDisp  
);

i was going to call it as:

CreateStdDispatch(
    myUnk,          //Pointer to the object's IUnknown implementation.
    anotherObject,  //Pointer to the object to expose.
    nil             //Pointer to the type information that describes the exposed object (i has no type info)
    dispInterface   //the IUnknown of the object that implements IDispatch for me
);

What i cannot figure out is how the Windows API implemention of CreateStdDispatch knows what methods to call on my object - especially since CreateStdDispatch doesn't know what object-oriented language i'm using, or its calling conventions.

How will CreateStdDispatch know

  • what method to call for a given dispid?
  • the calling convention of my language?
  • how to handle exceptions from the language that my object oriented object is written in?

Note: i have no choice but to implement a dispinterface; i didn't define the interface. i wish it was a simple early bound IUnknown, but it tisn't.

1条回答
虎瘦雄心在
2楼-- · 2019-04-10 04:06

Doesn't the ITypeInfo parameter passed into CreateStdDispatch expose all of the method information?

So you'd create type info first calling CreateDispTypeInfo and pass that through to CreateStdDispatch which can then use the type information to work out which method to call since CreateDispTypeInfo requires INTERFACEDATA which contains all this information

I could be way wrong since I don't have time to look into it but that would make sense to me. I'll investigate this later and update the answer.

查看更多
登录 后发表回答