The difference is that your version contains a bug, you should never return
a BSTR by reference from a _bstr_t wrapper without copying/detaching the
wrapped BSTR first. The _bstr_t wrapper manages it's own lifecycle, so
basically what you are doing is:
- Construction of a _bstr_t object
- Conversion of your str to a BSTR
- Assignment of the BSTR to large
- Destruction of the BSTR
so what you return a pointer to a destructed object hence the undefined
behavior.
What you need to do when using the CRT _bstr_t wrapper (or any other COM
wrapper class like CComBSTR) is:
// return the detached underlying BSTR from the wrapper
*large= _bstr_t(str.c_str()).Detach();
// return a copy of the underlying BSTR
or copy the wrapped BSTR first like..
*large= _bstr_t(str.c_str()).Copy();
In both cases ownership of the BSTR is transfered to the caller, so it's up
to the caller to free the BSTR., this is done automatically by the COM
interop layer in the CLR.
Willy.
"Gilad Walden" <Gi*********@discussions.microsoft.com> wrote in message
news:58**********************************@microsof t.com...
Thanks a lot! that worked. The way I allocated the BSTR in the ActiveX
before
was:
STDMETHODIMP CNoReg::GetLargeString(BSTR* large)
{
std::string str;
// making Str bigger than 50,000...
*large= _bstr_t(str.c_str());
return S_OK;
}
Can you tell me what's the difference between that and using CAtlString?
Thanks,
Gilad Walden.
"Willy Denoyette [MVP]" wrote:
"Gilad Walden" <Gi*********@discussions.microsoft.com> wrote in message
news:74**********************************@microsof t.com... >I have tested it with an Un-managed client (MFC) and exactly the same
>string
> that crashes .Net works fine in the MFC client.
>
Maybe you should post your code, anyway, this works for me...
//C++
STDMETHODIMP CNoReg::GetLargeString(BSTR* large){
const int buffSize = 65000;
wchar_t* pwStr = new wchar_t[buffSize];
wmemset(pwStr, 0, buffSize);
// Fill with all 'A', leave room for null char.
for (int i = 0;i < buffSize-1; i++)
pwStr[i] = L'A';
try {
CAtlString s(pwStr);
*large = s.AllocSysString();
}
catch(...){
return E_OUTOFMEMORY;
}
delete pwStr;
return S_OK;
}
//C#
string s = null;
LargeStringClass obj = new LargeStringClass ();
try {
obj.GetLargeString(out s);
...
Willy.