0

IUnknownシンクへのを受け入れるレガシー COM コントロール (コア) があります。目的は、コアがこのシンク インターフェイスを介してデータを読み書きできるようにすることです。コア/シンク ポインターは現在、レガシー システムで使用されており、簡単に変更することはできません。

私が抱えている問題は、マネージ コードから Core を呼び出して、マネージ コードにシンクを実装しようとする (試行する) オブジェクトを渡そうとしたときです。シンクを呼び出す準備ができているところまで Core をデバッグしました。通話の前 (後ではありません) に、次のようなメッセージが表示されます。

実行時チェックの失敗 #0 - ESP の値が関数呼び出しで適切に保存されませんでした...

私は純粋なレガシ コードでこれらを確認し、実行してきましたが、マネージ コードの導入には当惑しました。

以下は、私が必要だと考える 2 つのインターフェースの最小の表現です。

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

1 に答える 1

1

この ESP の問題は通常、DLL のランタイム ライブラリ間で何らかの混乱が生じていることを意味します。たとえば、私たちのコード ベースには多数の COM オブジェクトがあります。これらのオブジェクトの一部の現在の COM 登録がデバッグ ビルドからのものであり、他のオブジェクトの登録がリリース バージョンのものである場合、メソッドが呼び出されると ESP エラーが発生します。これらのオブジェクトが提供するインターフェース。

コードベースにあるすべての既知の COM オブジェクトを登録するスクリプトがあります。

于 2010-03-03T17:07:13.480 に答える