在托管(C#)代码中实现COM“接收器”

时间:2009-11-25 16:28:41

标签: c# iunknown

我有一个传统的COM控件(Core)接受IUnknown到接收器。目的是允许Core通过此接口接口读/写数据。 Core / Sink指针目前在旧系统中使用,不易修改。

我遇到的问题是当我尝试从托管代码调用Core并传入一个(尝试)在托管代码中实现接收器的对象时。我已经调试了核心,它准备调用接收器。在通话之前(而不是之后),我得到的消息类似于:

  

运行时检查失败#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 个答案:

答案 0 :(得分:1)

ESP问题通常意味着您在DLL的运行时库之间存在某种混淆。例如,在我们的代码库中有很多COM对象,如果其中一些对象的当前COM注册来自调试版本,而其他注册属于发布版本则会在调用方法时出现ESP错误这些对象提供的接口。

我有一个脚本可以注册我们代码库中的所有已知COM对象。