将字符串数组从C#传递到C ++ DLL函数并将其填充到DLL中并返回 [英] Passing an array of strings from C# to C++ DLL function and fill it in the DLL and get back

查看:135
本文介绍了将字符串数组从C#传递到C ++ DLL函数并将其填充到DLL中并返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个C#应用程序,该程序将大小为30的空字符串数组传递给C ++ DLL.该字符串数组需要填充到DLL中,并返回给C#应用程序.

I am writing a C# application that passes an empty string array of size 30 to a C++ DLL. This string array needs to be filled in the DLL and given back to the C# application.

我的代码在DLL的函数调用结束时观察到内存损坏.

I my code I observe memory corruption at the end of function call from DLL.

我的C ++ DLL代码如下:

My C++ DLL code is as follows:

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参数.这意味着调用者必须为每个字符串分配缓冲区,并知道缓冲区需要多大.

To make this current approach work you'd need to pass StringBuilder instances rather than string. That's because the data is flowing from caller to callee. The strings are out parameters. And that means that the caller has to allocate the buffers for each string, and know how large the buffers need to be.

在这里使用BSTR要容易得多.这使您可以在本机代码中分配字符串,并在托管代码中将它们释放.这是因为BSTR是分配在共享COM堆上的,而p/invoke marshaller可以理解它们.进行此轻微更改意味着调用者不需要知道字符串的大小.

It's much easier to use BSTR here. This allows you to allocate the strings in the native code, and have them deallocated in the managed code. That's because BSTR is allocated on the shared COM heap, and the p/invoke marshaller understands them. Making this slight change means that the caller does not need to know how large the strings are up front.

代码如下:

SAMPLEDLL_API BOOL InitExecution(BSTR* names, int count)
{
    for (int i = 0 ; i < count; i++)
        names[i] = SysAllocStr(...);
    return TRUE;
}

在C#端,您可以这样编写:

And on the C# side you write it like this:

[DllImport(@"mydll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool InitExecution(
    [Out] IntPtr[] names, 
    int count
);

然后您需要做一些工作才能从BSTR编组到C#string.

And then you've got a bit of work to marshal from BSTR to 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]);
}

这篇关于将字符串数组从C#传递到C ++ DLL函数并将其填充到DLL中并返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆