Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use C++ Component Object Model in C#

Tags:

c++

c#

com

I am trying to build a COM Library in C++, using a C# project for testing. Some methods need to return strings to the caller. On calling these methods from C# I get this: "Access violation reading at location ..."

This is the C++ code from my testproject (apart from all the stuff generated by 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;
}


In C# I just referenced the DLL from the COM-Tab, turned "Embed Interop Types" off, because it caused errors, and ran this:

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

The error occurs after leaving the Test-Method. I debugged the C++ code from within my C# project and the values are placed in the correct locations. I do not get the error if I try to return 0 (gives null in C#), even if I still allocate memory like in the example.

I can not make sense of the address, which the access violation complains about. It is neither the address I am allocating nor any other address used in the method. What also seems weird to me is that the CoTaskMemAlloc-Function always returns addresses with the first byte set to zero (0x00XXXXXX), but that might just be a COM thing.


I ran out of ideas and I cant find much information on this (except for basic COM tutorials) anywhere. Can anyone help?

like image 300
Wutz Avatar asked Sep 03 '12 13:09

Wutz


1 Answers

BSTRs require extra memory (to keep track of the string len) so must use SysAllocString() function to allocate BSTRs (or use one of the "smart" BSTR classes).

So your original code should read like:

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

A good reading about BSTRs: http://blogs.msdn.com/b/ericlippert/archive/2003/09/12/52976.aspx

like image 72
Vagaus Avatar answered Oct 24 '22 22:10

Vagaus