将字符串数组从C#传递到C++;DLL函数并将其填充到DLL中,然后返回 我正在编写一个C应用程序,它将一个大小为30的空字符串数组传递给C++ DLL。这个字符串数组需要填入DLL并返回给C#应用程序

将字符串数组从C#传递到C++;DLL函数并将其填充到DLL中,然后返回 我正在编写一个C应用程序,它将一个大小为30的空字符串数组传递给C++ DLL。这个字符串数组需要填入DLL并返回给C#应用程序,c#,pinvoke,dllimport,memory-corruption,stack-corruption,C#,Pinvoke,Dllimport,Memory Corruption,Stack Corruption,我在我的代码中观察到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";

我在我的代码中观察到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;
}

要使此当前方法有效,您需要传递
StringBuilder
实例,而不是
string
。这是因为数据从一个调用者流向另一个被调用者。字符串是输出参数。这意味着调用方必须为每个字符串分配缓冲区,并知道缓冲区需要有多大

在这里使用
BSTR
要容易得多。这允许您在本机代码中分配字符串,并在托管代码中释放它们。这是因为
BSTR
是在共享COM堆上分配的,并且p/invoke封送员理解它们。进行这个微小的更改意味着调用者不需要知道前面的字符串有多大

代码如下所示:

SAMPLEDLL_API BOOL InitExecution(BSTR* names, int count)
{
    for (int i = 0 ; i < count; i++)
        names[i] = SysAllocStr(...);
    return TRUE;
}
[DllImport(@"mydll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool InitExecution(
    [Out] IntPtr[] names, 
    int count
);
然后,您还需要做一些工作,从
BSTR
封送到C#
字符串

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]);
}
IntPtr[]namePtrs=newintptr[count];
初始化执行(namePtrs,namePtrs.Length);
字符串[]名称=新字符串[namePtrs.Length];
for(int i=0;i
C#字符串是不可变的。尝试传递一个
StringBuilder
。或者使用BSTR,而不必预先决定分配多少内存
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]);
}