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
I wonder if
Message
is called on a thread different from the one that created thecanreceiver
.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 byMessage
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.