How to safely pass string reference from c# to c++? -
i developing c# dll project c++ dll project.
let's c++ dll logins web site, , query on web server.
and c++ dll has return html code of web site.
in same time, c++ dll must save cookie data web site.
so, passed stringbuilder object c++ function.
i know how html code web site using httpwebrequest , httpwebresponse classed in c#, unfortunately have in c++ dll project.
so bear in mind, don't need c# codes.
i have tried passing string variable ref between c# dll , c++ dll.
passing stringbuilder c# , lptstr.
it works fine, strings missing result.
i couldn't find out reason.
anyway, here 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; (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 stringbuilder cookie, can carry on next url of web site.
(i using libcurl in c++ project.)
but problem have 100 ids.
when runs 3~40, returns heap error.
debug assertion failed! program: ~~~~mics\dbgheap.c line: 1424 expression: _pfirstblock == phead
i cannot click abort, retry or ignore button.
it looks c# application hangs.
i read many articles debug assertion failed dbgheap.
mostly free memory object heap.
i newbie 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 error not comes out in time.
so came across guess, happens when .net runs garbage collector.
.net garbage collector tries free memory created c++ dll , heap error.
am right?
i think he's suffering same problem mine.
what best way avoid heap error , return correct string c++ dll c# dll?
p/s: , heap error occurs when run debug mode. don't error when run release mode.
edit
according whozcraig answer, changed code below.
//return ::sysallocstring(ccombstr(html.c_str()).detach()); ccombstr res(html.c_str()); return res.detach();
but no luck, still heap error.
your question title asks passing string reference c# c++, later in text ask how return string c++ c#. also, tell new c++. in mind, i'll tell how did sort of interaction last time had that. made c++ side allocate and free memory, passing out c# intptr
s marshal.ptrtostringansi(p)
ed. in case, storing recerences thread-local in c++ , freeing them on each function call enough, can make c++ function frees whatever ref given. not intellectual , not efficient way, works.
upd: they say does. quick googling comes this article. think it's pretty good, can refer instead of suggestion. passing raw intptr
s if pointer not okay freed (like old delphi/c++builder style strings, example) , prefer bothered more on managed side on native side.
as example, piece of code doing delphi interaction (good c++ builder well):
// function get_ti_tc(aurafilename:pansichar; var ti,tc:pansichar):boolean; stdcall; external 'auratoiec104.dll' name 'get_ti_tc'; [dllimport("auratoiec104")] [return: marshalas(unmanagedtype.i1)] private static extern bool get_ti_tc(string aurafilename, out intptr ti, out intptr tc); public static bool get_ti_tc(string aurafilename, out string ti, out string tc) { intptr pti, ptc; bool result = get_ti_tc(aurafilename, out pti, out ptc); ti = marshal.ptrtostringansi(pti); tc = marshal.ptrtostringansi(ptc); return result; }
Comments
Post a Comment