我正在编写一个C#应用程序,它将大小为30的空字符串数组传递给C ++ DLL。需要在DLL中填充此字符串数组并将其返回给C#应用程序。
我的代码我在DLL的函数调用结束时观察到内存损坏。
我的C ++ DLL代码如下:
SAMPLEDLL_API BOOL InitExecution (wchar_t **paszStrings, int count)
{
for (int i = 0 ; i < count; i++)
{
mbstowcs(*(paszStrings + i), "Good",4);
//*(paszStrings + i) = "Good";
}
return TRUE;
}
我的C#代码是
string[] names = new[] { "Britto", "Regis" };
if (Wrapper1.InitExecution(ref names, names.Length) == 1)
MessageBox.Show("Passed");
[DllImport("MFCLibrary1.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern UInt32 InitExecution(ref string[] Names, int count);
答案 0 :(得分:2)
要使此当前方法有效,您需要传递StringBuilder
个实例而不是string
。那是因为数据从调用者流向被调用者。字符串是out参数。这意味着调用者必须为每个字符串分配缓冲区,并知道缓冲区需要多大。
在这里使用BSTR
要容易得多。这允许您在本机代码中分配字符串,并在托管代码中取消分配它们。那是因为BSTR
在共享的COM堆上分配,而p / invoke marshaller理解它们。进行这种微小的改变意味着调用者不需要知道前面的字符串有多大。
代码如下所示:
SAMPLEDLL_API BOOL InitExecution(BSTR* names, int count)
{
for (int i = 0 ; i < count; i++)
names[i] = SysAllocStr(...);
return TRUE;
}
在C#方面你可以这样写:
[DllImport(@"mydll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool InitExecution(
[Out] IntPtr[] names,
int count
);
然后你需要做一些工作,从BSTR
到C#string
进行编组。
IntPtr[] namePtrs = new IntPtr[count];
InitExecution(namePtrs, namePtrs.Length);
string[] names = new string[namePtrs.Length];
for (int i = 0; i < namePtrs.Length; i++)
{
names[i] = Marshal.PtrToStringBSTR(namePtrs[i]);
Marshal.FreeBSTR(namePtrs[i]);
}