Реализация COM-приемника в управляемом (C#) коде

У меня есть устаревший элемент управления COM (Core), который принимает IUnknown в раковину. Цель состоит в том, чтобы позволить ядру считывать / записывать данные через этот интерфейс приемника. Указатели Core/Sink в настоящее время используются в устаревших системах и не могут быть легко изменены.

У меня проблема, когда я пытаюсь вызвать ядро ​​из управляемого кода и передать объект, который (пытается) реализовать приемник в управляемом коде. Я отладил ядро ​​до такой степени, что оно готовится вызвать сток. До (не после) звонка я получаю сообщение, похожее на:

Ошибка проверки времени выполнения #0 - значение ESP не было должным образом сохранено при вызове функции...

Я видел и работал с ними в чистом унаследованном коде, но введение управляемого кода меня озадачило.

Вот самые маленькие представления двух интерфейсов, которые, я считаю, необходимы.

interface ICore : IDispatch
{
   [id(1), helpstring("method Init")] HRESULT Init([in] IUnknown *pDataManSink);

  HRESULT FireOnImport([in] LPCOLESTR pszFormName, [in] LPCOLESTR pszTagName, [in] VARIANT pszData);

   ... more methods
}

"Поток" доступа к данным из IDL (упрощен для упрощения демонстрации проблемы)

interface IDataManagerSinkEx : IUnknown
{
   [helpstring("method ReadData")] HRESULT ReadData([in] LPCTSTR pszDataKey, [out, retval] BSTR* pbsData);
   [helpstring("method WriteData")] HRESULT WriteData([in] LPCTSTR pszDataKey, [in] LPCTSTR pszData);
   [helpstring("method ReadDataEx")] HRESULT ReadTagEx([in] LPCTSTR pszDataKey, [out] short *pwExtraInfoOut, [out, retval] BSTR *pbsData);
   [helpstring("method WriteDataEx")] HRESULT WriteTagEx([in] LPCTSTR pszDataKey, [in] short wExtraInfo, [in] LPCTSTR pszData);
}

Я пробовал различные реализации приемника в C#, но безрезультатно или изменил условия ошибки. Вот самая последняя реализация, и да, я вручную написал определение интерфейса, так как использование одного из типов lib не сработало. (та же проблема)

[ComImport]
[Guid( "AB79770E-8143-45E6-B082-E985E6DFA5CB" )]
[InterfaceType( ComInterfaceType.InterfaceIsIUnknown )]
public interface IMyDataManagerSinkEx
{
  [PreserveSig]
  int ReadData( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, out string data );

  [PreserveSig]
  int WriteTag( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, [MarshalAs( UnmanagedType.LPStr )]string pszData );

  [PreserveSig]
  int ReadTagEx( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, out short pwExraInfoOut, out string dataOut );

  [PreserveSig]
  int WriteTagEx( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, short wExtraInfo, [MarshalAs( UnmanagedType.LPStr )]string pszData );
}

class public SinkImpl : IMyDataManagerSinkEx
{
  [PreserveSig]
  public int ReadData( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, out string data )
  {
     throw new NotImplementedException();
  }

  [PreserveSig]
  public int WriteTag( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, [MarshalAs( UnmanagedType.LPStr )]string pszData )
  {
     throw new NotImplementedException();
  }

  [PreserveSig]
  public int ReadTagEx( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, out short pwExraInfoOut, out string dataOut )
  {
     throw new NotImplementedException();
  }

  [PreserveSig]
  public int WriteTagEx( [MarshalAs( UnmanagedType.LPStr )]string pszDataKey, short wExtraInfo, [MarshalAs( UnmanagedType.LPStr )]string pszData )
  {
     throw new NotImplementedException();
  }
}

1 ответ

Эта проблема ESP обычно означает, что у вас есть какая-то путаница между библиотеками времени выполнения ваших DLL. Например, в нашей кодовой базе есть много COM-объектов, если текущая регистрация COM некоторых из этих объектов происходит из отладочной сборки, а другие - из релизных версий, вы получите ошибку ESP при вызове методов интерфейсы, которые предоставляют эти объекты.

У меня есть скрипт, который регистрирует все известные COM-объекты, которые находятся в нашей кодовой базе.

Другие вопросы по тегам