5

テスト用のC#プロジェクトを使用して、C++でCOMライブラリを構築しようとしています。一部のメソッドは、呼び出し元に文字列を返す必要があります。C#からこれらのメソッドを呼び出すと、「場所でのアクセス違反の読み取り...」というメッセージが表示されます。

これは私のテストプロジェクトからのC++コードです(VS 2010 ATLによって生成されたすべてのものを除く)

//COMTest.idl
[id(1)] HRESULT Test([out,retval] BSTR* ret);

//Program2.h
STDMETHOD(Test)(BSTR* ret);

//Program2.cpp
STDMETHODIMP CProgram2::Test(BSTR* ret)
{
   BSTR tmp = (BSTR)CoTaskMemAlloc(sizeof(wchar_t) * 2);
   tmp[0] = L'H';
   tmp[1] = L'\0';

   *ret = (BSTR)tmp;
   return S_OK;
}


C#では、COMタブからDLLを参照し、エラーが発生したため「埋め込み相互運用機能」をオフにして、次のコマンドを実行しました。

static void Main(string[] args)
{
   COMTestLib.Program2Class instance = new COMTestLib.Program2Class();
   string tmp = instance.Test(); //Where the error occurs

   Console.WriteLine(tmp); //This is not reached

   Console.Read();
}

テストメソッドを終了した後にエラーが発生します。C#プロジェクト内からC ++コードをデバッグしたところ、値が正しい場所に配置されました。例のようにメモリを割り当てても、0を返そうとしても(C#ではnullを指定)、エラーは発生しません。

アクセス違反が不満を言っているアドレスがわかりません。これは、私が割り当てているアドレスでも、メソッドで使用されている他のアドレスでもありません。また、私には奇妙に思えますが、CoTaskMemAlloc-Functionは常に最初のバイトがゼロ(0x00XXXXXX)に設定されたアドレスを返しますが、それは単なるCOMの問題である可能性があります。


私はアイデアを使い果たし、これに関する多くの情報(基本的なCOMチュートリアルを除く)をどこにも見つけることができません。誰か助けてもらえますか?

4

2 に答える 2

4

BSTRは(文字列lenを追跡するために)追加のメモリを必要とするため、SysAllocString()関数を使用してBSTRを割り当てる必要があります(または「スマート」BSTRクラスの1つを使用します)。

したがって、元のコードは次のようになります。

//Program2.cpp
STDMETHODIMP CProgram2::Test(BSTR* ret)
{
   *ret = SysAllocString(L"H");
   return S_OK;
}

BSTRについての良い読み物:http://blogs.msdn.com/b/ericlippert/archive/2003/09/12/52976.aspx

于 2012-09-03T19:54:30.923 に答える
1

COMプロジェクトとテストプロジェクトの両方がSTAであることを確認してください。ビットネスもチェックしてください。BSTRをLPSTRに置き換えるとどうなりますか?

于 2012-09-03T14:09:20.537 に答える