QueryInterface fails at casting inside COM-interface implementation

2k views Asked by At

I am creating a tool in c# to retrieve messages of a CAN-network (network in a car) using an Dll written in C/C++. This dll is usable as a COM-interface.

My c#-formclass implements one of these COM-interfaces. And other variables are instantiated using these COM-interfaces (everything works perfect).

The problem: The interface my C#-form implements has 3 abstract functions. One of these functions is called -by the dll- and i need to implement it myself. In this function i wish to retrieve a property of a form-wide variable that is of a COM-type.

The COM library is CANSUPPORTLib

The form-wide variable:

private CANSUPPORTLib.ICanIOEx devices = new CANSUPPORTLib.CanIO();

This variable is also form-wide and is retrieved via the devices-variable:

canreceiver = (CANSUPPORTLib.IDirectCAN2)devices.get_DirectDispatch(receiverLogicalChannel);

The function that is called by the dll and implemented in c#

    public void Message(double dTimeStamp)
    {
        Console.WriteLine("!!! message ontvangen !!!" + Environment.NewLine);

        try
        {
            CANSUPPORTLib.can_msg_tag message = new CANSUPPORTLib.can_msg_tag();
            message = (CANSUPPORTLib.can_msg_tag)System.Runtime.InteropServices.Marshal.PtrToStructure(canreceiver.RawMessage, message.GetType());
            for (int i = 0; i < message.data.Length; i++)
            {
                Console.WriteLine("byte " + i + ": " + message.data[i]);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

The error rises at this line:

message = (CANSUPPORTLib.can_msg_tag)System.Runtime.InteropServices.Marshal.PtrToStructure(canreceiver.RawMessage, message.GetType());

Error:

Unable to cast COM object of type 'System.__ComObject' to interface type CANSUPPORTLib.IDirectCAN2'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{33373EFC-DB42-48C4-A719-3730B7F228B5}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

Notes: It is possible to have a timer-clock that checks every 100ms for the message i need. The message is then retrieved in the exact same way as i do now. This timer is started when the form starts. The checking is only done when Message(double) has put a variable to true (a message arrived).

When the timer-clock is started in the Message function, i have the same error as above

Starting another thread when the form starts, is also not possible.

Is there someone with experience with COM-interop ?

When this timer

1

There are 1 answers

5
Kim Gräsman On

I wonder if Message is called on a thread different from the one that created the canreceiver.

Do you know the threading model of CANSUPPORTLib.CanIO? If it's apartment-threaded, you may need to marshal a reference from the main UI thread to the thread called by Message somehow.

Alternatively, assuming you can change the source code of the C++ dll, and depending on your other threading requirements and constraints, you could change it to be free-threaded, in which case an object can be simultaneously accessed from multiple threads without marshalling.