QueryInterface失败在COM接口实现内部铸造

问题描述:

我正在c#中创建一个工具来检索使用C/C++编写的DLL的CAN网络(汽车网络)的消息。这个DLL可用作COM接口。QueryInterface失败在COM接口实现内部铸造

我的c#-formclass实现了其中一个COM接口。其他变量使用这些COM接口实例化(一切都很完美)。

问题:我的C#-form实现的接口有3个抽象函数。其中一个函数叫做-by dll-,我需要自己实现它。在这个函数中,我希望检索一个COM类型的表单变量属性。

COM库是CANSUPPORTLib

该形状宽变量:

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

此变量也形状宽,并且经由设备变量检索:

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

的函数,由dll调用并在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); 
     } 
    } 

误差上升在这一行:

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

错误:

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)). 

注: 有可能有一个定时器时钟来检查我需要的消息每隔100ms。然后以与我现在完全相同的方式检索该消息。这个计时器在表单开始时启动。只有当Message(double)将变量设置为true(消息到达)时才会执行检查。

当定时器时钟在消息功能被启动时,我有相同的错误如上

启动另一个线程的形式开始时,也不可能。

是否有人有COM-interop经验?

当该定时器

+0

让我感到困惑的是,在调用get_DirectDispatch的结果时发生这样的错误,而不是在调用PtrToStructure时发生。你确定导致错误的行吗? – Timores 2010-03-18 13:22:59

+0

我很确定这件事。在另一个函数中,我发送消息,并通过dll函数捕获通知并获取消息。在调试send()函数时,我可以完全访问canreceiver变量并查看RawMessage的值,但不是在我处于Message()函数中时( - >这是COM接口的实现 – brecht 2010-03-18 14:06:40

不知Message上被调用创建该canreceiver的一个不同的线程。

你知道CANSUPPORTLib.CanIO的线程模型吗?如果它是单元线程的,那么您可能需要将主UI线程的引用以某种方式编号为Message。或者,假设您可以更改C++ dll的源代码,并根据您的其他线程要求和约束,可以将其更改为*线程,在这种情况下,可以从多个线程同时访问一个对象没有编组。

+0

是的,它是我注意到的一个不同的线程,当我在message()和sendmessage()中打印thread-id时,它是不同的,我可以看到dll-source,但我不允许更改代码。 事实上:我现在正在实现的是需要在C++中实现的,我会遇到同样的问题吗? – brecht 2010-03-19 15:59:01

+0

是的,这取决于你为C++实现选择的线程模型,线程模型决定了COM运行时保护对象不受并发访问 我认为WinForms应用程序的默认线程模型是Apartment(由主方法上的[STAThread]属性管理) - 这个我一次只有一个线程可以调用同一个房间中的任何一个对象,例如,你的形式。 – 2010-03-23 09:36:29

+0

因此,无论是在使用接口指针时都需要将主线程的接口指针编组到工作线程,还是需要让C++实现具有与C#代码相同的线程模型。 不幸的是我找不到托管代码中编组接口指针的任何信息。 一个简单的解决方案可能是让C++代码将'this'指针作为参数传递给'Message',此时COM运行时必须为您整理编组。由于将编组接口指针发送给方法,因此不需要从回调中访问'canreceiver'。 – 2010-03-23 09:38:01