在C#中使用C ++组件对象模型

时间:2012-09-03 13:38:47

标签: c# c++ com

我正在尝试用C ++构建一个COM库,使用C#项目进行测试。某些方法需要将字符串返回给调用者。在从C#调用这些方法时,我得到:“在位置读取访问冲突...”

这是我的testproject的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-Tab引用了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教程)。有人可以帮忙吗?

2 个答案:

答案 0 :(得分:3)

BSTR需要额外的内存(以跟踪字符串len),因此必须使用SysAllocString()函数来分配BSTR(或使用“ smart ”BSTR类之一)。

因此您的原始代码应如下所示:

//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

答案 1 :(得分:0)

检查您的COM项目和测试项目是否都是STA。检查位数。如果用LPSTR替换BSTR怎么办?