2010-03-18 2 views
0

Я создаю инструмент в C# для получения сообщений CAN-сети (сеть в автомобиле) с использованием Dll, написанной на C/C++. Эта DLL может использоваться как COM-интерфейс.QueryInterface не удается выполнить литье внутри реализации COM-интерфейса

My C# -formclass реализует один из этих COM-интерфейсов. И другие переменные создаются с использованием этих COM-интерфейсов (все работает отлично).

Проблема: Интерфейс моих инструментов C# -form имеет 3 абстрактные функции. Одна из этих функций называется - dll - и мне нужно реализовать ее самостоятельно. В этой функции я хочу получить свойство переменной формы, имеющей тип 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)). 

Примечания: Вполне возможно, иметь таймер-часы, который проверяет каждые 100 мс для сообщения мне нужно. Затем сообщение извлекается точно так же, как и сейчас. Этот таймер запускается при запуске формы. Проверка выполняется только тогда, когда Message (double) поставил переменную в true (сообщение появилось).

Когда таймер-часы запускается в функции сообщения, я иметь такую ​​же ошибку, как выше

Начиная другой поток при запуске формы, также не представляется возможным.

Есть ли у кого-нибудь опыт работы с COM-interop?

Когда таймер

+0

Что меня озадачивает, так это может произойти при передаче результата вызова get_DirectDispatch, а не при вызове PtrToStructure. Вы уверены в строке, вызывающей ошибку? – Timores

+0

Я уверенно верю в это. В другой функции я отправляю сообщение и через DLL-функции, улавливая уведомление и получая сообщение.При отладке функции send() я могу отлично получить доступ к переменной canreceiver и увидеть значение RawMessage, но не пока я в функции Message() (-> это реализация COM-интерфейса – brecht

ответ

0

Интересно, если Message называется на нитку, отличной от той, которая создала canreceiver.

Знаете ли вы модель резьбы CANSUPPORTLib.CanIO? Если это потолочная квартира, вам может понадобиться как-то маршализовать ссылку из основного потока пользовательского интерфейса на поток, называемый Message.

В качестве альтернативы, если вы можете изменить исходный код dll C++, и в зависимости от ваших других требований и ограничений потоковой передачи вы можете изменить его на свободную нитью, и в этом случае к объекту можно одновременно получить доступ из нескольких потоков без сортировки.

+0

Да, это другой поток, который я заметил. Когда я печатаю идентификатор потока в сообщении() и в sendmessage(), он отличается. Я вижу DLL-источник, но мне не разрешено изменять код. Дело в том, что то, что я реализую сейчас, необходимо реализовать в C++. Будет ли у меня такая же проблема? – brecht

+0

Да, в зависимости от модели потока, которую вы выбираете для реализации C++. Модель потоковой передачи определяет, как среда выполнения COM защищает объект от одновременного доступа. Я думаю, что модель по умолчанию для WinForms по умолчанию - Apartment (управляется атрибутом '[STAThread]' по основному методу) - это мне что только один поток за раз может вызывать любой объект в той же квартире, например. ваша форма. –

+0

Итак, нужно либо маршалировать указатель интерфейса из основного потока на рабочий поток перед его использованием, либо вам нужно, чтобы реализация C++ имела ту же модель потоков, что и код C#. К сожалению, я не могу найти информацию о указателях маршаллинга в управляемом коде. Простым решением может быть, чтобы код C++ передавал свой указатель 'this' в качестве аргумента в' Message', в этот момент времени выполнения COM пришлось бы сортировать маршаллинг для вас. Поскольку маркерный указатель интерфейса отправляется методу, вам не нужно обращаться к «canreceiver» из обратного вызова. –

Смежные вопросы