0

我有一个接受接收IUnknown器的旧 COM 控件(核心)。目的是让 Core 通过这个 sink 接口读/写数据。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# 中尝试了各种接收器的实现,但无济于事或错误条件发生变化。这是最新的实现,是的,我手动编码了接口定义,因为使用类型库中的那个不起作用。(同样的问题)

[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();
  }
}
4

1 回答 1

1

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

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

于 2010-03-03T17:07:13.480 回答