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 

enter image description here

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# intptrs 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 intptrs 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

Popular posts from this blog

c++ - Creating new partition disk winapi -

VBA function to include CDATA -

php - Warning: file_get_contents() expects parameter 1 to be a valid path, array given 16 -