Как объявить IStream в режиме ожидания, чтобы Visual Studio сопоставила его с s.w.interop.comtypes?

У меня есть COM-объект, который принимает поток от клиента C# и обрабатывает его. Казалось бы, я должен использовать IStream. Поэтому я пишу свой холостой ход, как показано ниже. Затем я использую MIDL для компиляции в tlb и компилирую свое решение, регистрирую его, а затем добавляю ссылку на мою библиотеку в проект C#.

Visual Studio создает определение IStream в моей собственной библиотеке. Как я могу остановить это и заставить его использовать COMTypes IStream? Кажется, будет один из 3 ответов: добавить импорт

  • в idl, чтобы он не повторно объявлял IStream (импорт MSCOREE делает это, но не решает проблему C #)
  • каким-то образом псевдоним IStream в визуальной студии, но я не понимаю, как это сделать.
  • Все мои мысли совершенно неверны, и мне вообще не следует использовать IStream.

помогите... спасибо

[
  uuid(3AC11584-7F6A-493A-9C90-588560DF8769),
  version(1.0),
]
library TestLibrary
{

  importlib("stdole2.tlb");

  [
    uuid(09FF25EC-6A21-423B-A5FD-BCB691F93C0C),
    version(1.0),
    helpstring("Just for testing"),
    dual,
    nonextensible,
    oleautomation
  ]
  interface ITest: IDispatch
  {
    [id(0x00000006),helpstring("Testing stream")]
    HRESULT _stdcall LoadFromStream([in] IStream * stream, [out, retval] IMyTest ** ResultValue);
  };

  [
    uuid(CC2864E4-55BA-4057-8687-29153BE3E046),
    noncreatable,
    version(1.0)
  ]
  coclass HCTest
  {
     [default] interface ITest;
  };

};

person Grahame Grieve    schedule 22.04.2010    source источник


Ответы (2)


Это не требует исправления, оболочка взаимодействия, созданная из библиотеки типов, будет в порядке. Объявление ComTypes.IStream позволяет управляемому коду реализовать COM-сервер, который реализует IStream или принимает его в качестве аргумента. Многие классы .NET Framework делают это.

person Hans Passant    schedule 22.04.2010
comment
благодаря. Итак, всем нужна отдельная оболочка для каждой COM-библиотеки, использующей IStream? Кроме того, импортированная оболочка IStream, которую я получаю, сильно отличается от ComTypes IStream. У него даже нет таких операций, и как вы реализуете эту?: void RemoteRead(out byte pv, uint cb, out uint pcbRead); Можете ли вы прочитать только один байт за раз? - person Grahame Grieve; 23.04.2010
comment
Обертка — это просто объявление. Мне кажется, вы нашли что-то еще, кроме простого IStream. Может прокси. - person Hans Passant; 23.04.2010
comment
@HansPassant Боюсь, это неправда (по крайней мере, по моему опыту). У меня есть несколько (C++) COM-классов, которые экспортируют функции с одним параметром, определенным как IStream, и ни один из них не будет принимать объект, реализующий ComTypes.IStream, все они получают собственное внутреннее определение IStream и приводят объект, реализующий ComTypes.IStream. тем тоже не помогает. - person yms; 11.04.2012

То, что вы видите и испытываете, является особенностью (часто раздражающей) компилятора MIDL. Определение любого типа, на который есть ссылка в разделе «библиотека», будет введено в tlb (библиотеку типов); за исключением интерфейса IUnknown и базовые типы MIDL (и, возможно, еще несколько примитивных типов). Те странные методы, которые вы видите в «вашем» IStream, исходят из базового типа ISequentialStream. У вас есть несколько вариантов:

  1. Борьба с компилятором MIDL в течение нескольких дней, чтобы попытаться получить его от внедрения IStream (и всех других его поддерживающих типов). Я сделал это. Так было и с Мскори. Проблема в том, что компилятор MIDL автоматически импортирует "oaidl.idl", когда встречает библиотечный оператор. Таким образом, эти типы (Stream и т. д.) уже внедрены в текущий контекст IDL, прежде чем вы сможете что-либо с этим сделать. Это плохо документированная функция. Суть в том, что он будет делать это независимо от того, что вы делаете, если вы не удалите жесткие ссылки на IStream (используйте поток PVOID [*]).

  2. Игнорируй это. Даже не используйте его. Вместо этого используйте System.Runtime.InteropServices.ComTypes.IStream. Пока используемый вами интерфейс (в .Net) помечен правильными атрибутами (Guid, InterfaceType и т. д.), они взаимозаменяемы. Вам придется либо отредактировать библиотеку типов, либо код взаимодействия, чтобы он принимал тип, который вы хотите передать. Я бы выбрал объект, чтобы вы могли использовать любой интерфейс IStream (с допустимым определением). А также не используйте старый инструмент TlbImp. Используйте новый TlbImp2 (написанный на C# и с открытым исходным кодом) https://clrinterop.codeplex.com/releases/view/17579. Это позволяет вам действительно настроить преобразование из TLB в Managed, и вы можете создавать исходные файлы вместо/в дополнение к скомпилированной dll взаимодействия.

person Paul Easter    schedule 24.09.2014
comment
Большое спасибо за это - чтобы объяснить - в пункте 2 выше вы должны посетить страницу clrinterop на законсервированном сайте codeplex, нажать кнопку [скачать архив], а затем собрать инструмент tlbimp2 из заархивированного исходники включены в архив. Нет готового tlbimp2 - person Brian THOMAS; 15.02.2019