PInvoke: error saving text from C ++ to C #

I use Pinvoke for the interaction between Native (C ++) code and managed (C #) code. What I want to achieve is to get some text from the native code into my managed code as the return value. I. My C # code calls my C ++ function, which returns some text back to C #. Below is my code for this.

C ++ Code:

static std::wstring WSTR_TEMP; wchar_t* cppReturnSomeText() { UnicodeString usText ("Some Text Here"); WSTR_TEMP = ECUtilsICU::UniCodeStringToWString(usText); return (wchar_t *)(WSTR_TEMP.c_str()); } 

C # code:

 [DllImport(MY_DLL_NAME] [return: MarshalAs(UnmanagedType.LPWStr)] private static extern string cppReturnSomeText(); public static string GetSomeText() { string s = cppReturnSomeText(); return s; } 

Everything worked fine, as expected. Now I just change my operating system from WinXP (32Bit) to Win7 (64Bit). And when I ran this code, an error occurred:

"Trying to read or write protected memory. This often indicates that the other memory is corrupt."

+4
source share
1 answer

I assume the problem is that you are allocating memory using the C ++ runtime manager, but then the C # marshaller tries to free it. This will not work. You need to select and release the allocated allocator.

The best way I know to solve your problem is to marshal with BSTR . This uses a COM distributor, which is happy to share between native and managed modules.

 #include <comutil.h> BSTR cppReturnSomeText() { UnicodeString usText("Some Text Here"); std::wstring result = ECUtilsICU::UniCodeStringToWString(usText); return ::SysAllocString(result.c_str()); } 

On the C # side, you do the following:

 [DllImport(MY_DLL_NAME, CallingConvention=CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.BStr)] private static extern string cppReturnSomeText(); 

Another advantage of this is that your code is now thread safe because you no longer need a global variable.

+2
source

All Articles