By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,611 Members | 1,629 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,611 IT Pros & Developers. It's quick & easy.

problem in accessing a BSTR* from C#

P: n/a
I use C# in .NET framework.
I have an ActiveX implemented in C++ that has a COM interface method that
gets as it’s out parameter a BSTR* . The interop translates this BSTR* into
C# string. From my managed code, I am calling that function with ‘out’
parameter of ‘string’ type. For normal size strings it works fine, but when
the string is very big (> 50,000 bytes), I get a null exception from the COM
interop.
What is the reason? How to solve this problem?

Thanks in advance.
Nov 17 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
Hey Gilad,

Try using MarhsalAs attribute ont the function with BSTR.

Refer to MSDN for further information on the MarshalAs attribute.

-Moty-

"Gilad Walden" <Gi*********@discussions.microsoft.com> wrote in message
news:44**********************************@microsof t.com...
I use C# in .NET framework.
I have an ActiveX implemented in C++ that has a COM interface method that
gets as its out parameter a BSTR* . The interop translates this BSTR*
into
C# string. From my managed code, I am calling that function with out
parameter of string type. For normal size strings it works fine, but
when
the string is very big (> 50,000 bytes), I get a null exception from the
COM
interop.
What is the reason? How to solve this problem?

Thanks in advance.

Nov 17 '05 #2

P: n/a
But the Interop wrapper to the ActiveX is created automatically by VS.NET
when we drag the ActiveX into a form. we have no control on how it is being
done.

"Moty Michaely" wrote:
Hey Gilad,

Try using MarhsalAs attribute ont the function with BSTR.

Refer to MSDN for further information on the MarshalAs attribute.

-Moty-

"Gilad Walden" <Gi*********@discussions.microsoft.com> wrote in message
news:44**********************************@microsof t.com...
I use C# in .NET framework.
I have an ActiveX implemented in C++ that has a COM interface method that
gets as it’s out parameter a BSTR* . The interop translates this BSTR*
into
C# string. From my managed code, I am calling that function with ‘out’
parameter of ‘string’ type. For normal size strings it works fine, but
when
the string is very big (> 50,000 bytes), I get a null exception from the
COM
interop.
What is the reason? How to solve this problem?

Thanks in advance.


Nov 17 '05 #3

P: n/a
Are you sure the ActiveX component is designed to deal with that large BSTR?

Willy.

"Gilad Walden" <Gi*********@discussions.microsoft.com> wrote in message
news:44**********************************@microsof t.com...
I use C# in .NET framework.
I have an ActiveX implemented in C++ that has a COM interface method that
gets as it’s out parameter a BSTR* . The interop translates this BSTR*
into
C# string. From my managed code, I am calling that function with ‘out’
parameter of ‘string’ type. For normal size strings it works fine,
but when
the string is very big (> 50,000 bytes), I get a null exception from the
COM
interop.
What is the reason? How to solve this problem?

Thanks in advance.

Nov 17 '05 #4

P: n/a
I have tested it with an Un-managed client (MFC) and exactly the same string
that crashes .Net works fine in the MFC client.

"Willy Denoyette [MVP]" wrote:
Are you sure the ActiveX component is designed to deal with that large BSTR?

Willy.

"Gilad Walden" <Gi*********@discussions.microsoft.com> wrote in message
news:44**********************************@microsof t.com...
I use C# in .NET framework.
I have an ActiveX implemented in C++ that has a COM interface method that
gets as it’s out parameter a BSTR* . The interop translates this BSTR*
into
C# string. From my managed code, I am calling that function with ‘out’
parameter of ‘string’ type. For normal size strings it works fine,
but when
the string is very big (> 50,000 bytes), I get a null exception from the
COM
interop.
What is the reason? How to solve this problem?

Thanks in advance.


Nov 17 '05 #5

P: n/a

"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.
Nov 17 '05 #6

P: n/a
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.

Nov 17 '05 #7

P: n/a
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.

Nov 17 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.