Search code examples
c++visual-c++mfccomactivex

Invoking methods on ActiveX interface without a Wrapper class


I am using a 3d party ActiveX component for which there is no source code. I can add the component to my MFC dialog . When I do that, a wrapper class gets created with lots of functions which look like this:

void SetNextMovePCI2FastLink(short nNodeNumber, short nCardNumber)
    {
        static BYTE parms[] = VTS_I2 VTS_I2 ;
        InvokeHelper(0x109, DISPATCH_METHOD, VT_EMPTY, NULL, parms, nNodeNumber, nCardNumber);
    }

Using these wrapper functions I can have normal operation. However, due to accessing the COM object from different threads, I need to marshal the COM Interface for this object. How do I invoke methods on the COM Interface directly without the wrapper? Is there a simple way to apply the wrapper to the raw COM interface, so wrapper could be back in use? Or do I have to use IDispatch interface's Invoke() method? If so, is there a way to find out what are the true method name strings to call? The wrapper uses numbers such as 0x109 above to address each method. Can I somehow harness the wrapper's InvokeHelper() to call methods directly on a given COM interface?


Solution

  • I am quoting a response by Igor Tandetnik:

    "It's been a while since I used MFC, so my recollection is vague. The wrapper, I believe, is derived from COleDispatchDriver, which has a constructor from IDispatch as well as AttachDispatch method. Using these, you might be able to obtain the raw IDispatch pointer, marshal it to another thread, and there create a new wrapper instance and attach the pointer to it."

    Basically if you want to be using your MFC wrapper for COM/ActiveX objects after marshaling to another thread, you can use COleDispatchDriver to wrap your IDispatch and use some macro magic to tweek the code to invoke the same InvokeHelper(..) calls on the driver object. Alternatively extend the wrapper to use include acting on marshaled interface through the driver like the code below. Thanks, Igor.

    void SetCommsWrite(short nAddress, float fValue)
    {
        static BYTE parms[] = VTS_I2 VTS_R4 ;
        InvokeHelper(0x136, DISPATCH_METHOD, VT_EMPTY, NULL, parms, nAddress, fValue);
    }
    void SetCommsWrite(short nAddress, float fValue, COleDispatchDriver & driver)
    {
        static BYTE parms[] = VTS_I2 VTS_R4;
        driver.InvokeHelper(0x136, DISPATCH_METHOD, VT_EMPTY, NULL, parms, nAddress, fValue);
    }