2015-10-20 71 views
0

我們有使用回調方法從C++項目接收數據C#應用程序:C++內存泄漏將字符串傳遞到C#代碼

/* c# code */ 
call[UnmanagedFunctionPointer(CallingConvention.StdCall)] 
private unsafe delegate void NewFrame(string serial, Int32* width, Int32* height, short* frame); 

在我們的C++項目(從攝像機接收數據),我們非常頻繁地調用這個'NewFrame'回調方法,將相機幀傳遞給c#代碼。

在C++中這種方法的定義是:

/* c++ code */ 
typedef void (__stdcall * NewFrame)(char* serialnumber, INT32* width,INT32* height, int16_t* frame); 

要通過 '串行',WHE一個C++字符串對象轉換爲在c一個char * ++代碼:

/* c++ code */ 
char* stringToCsharpString(string s){ 
    char* cserial = new char[s.length() + 1]; 
    strcpy(cserial, s.c_str()); 
    return cserial; 
} 

然而這會導致(堆)內存泄漏,因爲cserial對象沒有被釋放。

這是本newFrame的方法是如何調用C++:

/* c++ code */ 
newFrame(stringToCsharpString(node.getSerialNumber()), &w, &h, data.frame); 

我們能做些什麼來解決這個問題?我們精通c#,但在C++中完全沒有。因此,談到C++代碼時,請說明徹底:)

+0

你需要在C#wrapper對象的Dispose()方法中刪除這個動態內存 –

+2

它也取決於NewFrame對字符串做了什麼。如果訪問是隻讀和同步的,並且指針不存儲在任何地方(即調用者等待完成並且'NewFrame()'以某種方式複製和/或轉換數據),則可以使用's.c_str()'作爲適當的爭論。 –

+0

無論如何,你不應該在模塊邊界上傳遞諸如'std :: string'這樣的類。 C#對'std :: string'一無所知,它是內部實現等。對NewFrame的參數應該只是一個指向C#創建的字符緩衝區(數組)的指針,不能少於。 – PaulMcKenzie

回答

0

爲C++託管內存到C#託管內存轉換,你可以使用gcnew

String^ ConvertUnmanagedString2ManagedString(char* cserial) 
{ 
    return gcnew String(cserial) 
} 

在這裏,我假設你的cserial內容編碼是UCS-2課程。我不知道cserial的內容是什麼,但是如果它使用UTF8或UCS-2以外的其他編碼進行編碼,則還需要應用文本編碼轉換,因爲C#字符串編碼是UCS-2。