Marshal wchar_t**
-
Wednesday, August 26, 2009 2:48 PMIn C++ I have:
extern "C" __declspec(dllexport) int myfunct(wchar_t** mystring) { *mystring = new wchar_t[wcslen(_T("hello world")); wcscpy(*mystring,_T("hello world")); return 1; }
In C#
[DllImport("myDll.dll")] internal static extern int myfunct([MarshalAs(UnmanagedType.LPWStr)]out string ec); public void test() { string str = null; int y = myfunct(out str); }
In windows Xp it works, but in windows Vista I get
"Attempted to read or write protected memory. This is often an indication that other memory is corrupt"Then I changed C# code in :
[DllImport("myDll.dll")] internal static extern int myfunct(out IntPtr ec); public void test() { IntPtr str; int y = myfunct(out str); string mystr = Marshal.PtrToStringUni(str); }
In this way it works on windows Vista, but is it right? is it just luck?
Do I forget something? should I free the memory?
All Replies
-
Wednesday, August 26, 2009 2:53 PMModerator
The C/C++ code is buggy. You need to allocate memory for the terminating NULL. So that'd be wcslen(...) + 1.
http://blog.voidnish.com -
Wednesday, August 26, 2009 2:58 PM
The C/C++ code is buggy. You need to allocate memory for the terminating NULL. So that'd be wcslen(...) + 1.
http://blog.voidnish.com
uops. Thank you ;)
insead for the marshal operation could you say me if there are possible problems? -
Wednesday, August 26, 2009 4:36 PMModerator
There's another big problem. The callee of this function must release the string. The C# code cannot do this, it doesn't have access to the unmanaged C/C++ heap allocator. You'll leak memory for every call.
The C/C++ code must look like this:
extern "C" __declspec(dllexport) int myfunct(wchar_t* buffer, size_t bufsize)
{
wcscpy_s(buffer, bufsize, L"Hello world");
return 1;
}
And your C# code like this:
[DllExport("something.dll", CharSet = CharSet.Unicode)]
private static extern int myfunct(StringBuilder buffer, int bufsize);
...
sb = new StringBuilder(666);
int retval = myfunct(sb, sb.Capacity);
string s = sb.ToString();
Hans Passant.- Marked As Answer by chiara1990 Thursday, August 27, 2009 3:22 PM
-
Wednesday, August 26, 2009 6:56 PMModeratorHey Hans,
I have not verified this, but I have this vague memory that if you use CoTaskMemAlloc (instead of directly using new/malloc), the interop marshaller may free the memory before marshaling to a System.String.
http://blog.voidnish.com

