I am developing a C# dll project with C++ dll project.
Let's say that C++ dll logins to a certain web site, and do some query on the web server.
And C++ dll has to return that html code of a web site.
In the same time, C++ dll must save the cookie data from the web site.
So, I passed StringBuilder object to C++ function.
I already know how to get html code from a web site using HttpWebRequest and HttpWebResponse classed in C#, but unfortunately I have to do it in C++ dll project.
So bear in mind, I don't need any C# codes.
I have tried Passing a string variable as a ref between a c# dll and c++ dll.
Passing StringBuilder from C# and get it as LPTSTR.
It works fine, but some strings were missing from the result.
I couldn't find out the reason.
Anyway, here is my code.
C++
extern "C" __declspec(dllexport) BSTR LoginQuery(const char* UserID, const char* UserPW, char Cookies[])
{
std::string html;
try
{
std::map<std::string, std::string> cookies;
MyClass *myclass = new MyClass();
html = myclass->LoginQuery(UserID, UserPW, cookies);
// Response cookies
std::string cookieData;
for (std::map<std::string, std::string>::iterator iterator = cookies.begin(); iterator != cookies.end(); iterator++)
{
cookieData += iterator->first;
cookieData += "=";
cookieData += iterator->second;
cookieData += ";";
}
sprintf(Cookies, cookieData.c_str(), 0);
delete myclass;
}
catch (...)
{
}
return ::SysAllocString(CComBSTR(html.c_str()).Detach());
}
C#
[DllImport(@"MyDll.dll", EntryPoint="LoginQuery", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern void LoginQuery(string UserID, string UserPW, StringBuilder Cookies);
void SomeThing()
{
StringBuilder _cookies = new StringBuilder(1024);
string result = LoginQuery("test", "1234", _cookies);
}
It works fine.
With the StringBuilder as cookie, I can carry on the next url of the web site.
(I am using libcurl in C++ project.)
But the problem is that I have about 100 ids.
When it runs about 3~40, it returns heap error.
Debug Assertion Failed!
Program: ~~~~mics\dbgheap.c
Line: 1424
Expression: _pFirstBlock == pHead
I cannot click the abort, retry or ignore button.
It looks like C# application hangs.
I read so many articles about debug assertion failed with dbgheap.
Mostly like free memory object from another heap.
I am newbie to C++.
I read Edson's question on http://bytes.com/topic/c-sharp/answers/812465-best-way-interop-c-system-string-c-std-string.
But the error does not always comes out in certain time.
So I came across with a guess, that it happens when .NET runs garbage collector.
.NET garbage collector tries to free some memory which created from C++ dll and I get the heap error.
Am I right?
I think he's suffering same problem as mine.
What is the best way to avoid heap error and return correct string from C++ dll to C# dll?
P/S: And the heap error occurs only when I run it debug mode. I don't get the error when I run release mode.
EDIT
According to WhozCraig answer, I changed my code as below.
//return ::SysAllocString(CComBSTR(html.c_str()).Detach());
CComBSTR res(html.c_str());
return res.Detach();
But no luck, I still get the heap error.