繁体   English   中英

将一个字符串数组从C#传递给C ++ DLL函数并将其填入DLL并返回

[英]Passing an array of strings from C# to C++ DLL function and fill it in the DLL and get back

我正在编写一个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);

要使当前的方法工作,您需要传递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]);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM