将字符串数组作为缓冲区传递给C ++到C#

时间:2014-07-18 11:27:48

标签: c# c++ marshalling

我有一些非托管C ++动态库和C#GUI应用程序,使用它。我需要将已知大小的字符串数组传递给C ++库,然后填充它。还有最大字符串长度值:

// C++ part
#define MAX_SOME_STRING_LEN 250;

MYDLL_API uint8_t __stdcall  getSomeStrings(wchar_t** strings, uint64_t count) {
    /// populate strings, not more characters then MAX_SOME_STRING_LEN for each string
    return 0;
}

// C# part
[DllImport("biosec_lib.dll", CallingConvention = CallingConvention.StdCall)]
    static extern Byte getSomeStrings(string[] providers, UInt64 size);

我想避免在C ++库端进行数组内存管理。我通过其他库API调用获得了理想的字符串数组大小。然后在C#端分配合适的数组并调用此API方法,传递合适的数组。

  1. 这是一个好方法吗?有没有更好的方法?在将数据传递给API方法之前,我可以为数组中的每个字符串保留MAX_SOME_STRING_LEN大小吗?

2 个答案:

答案 0 :(得分:0)

这是一种不同的方法。您应该分配一种“非托管”缓冲区,传递给DLL然后转换结果并释放缓冲区。它与C语言完全相同,但是从托管环境调用。

您的DLL的签名将类似于:

[DllImport("biosec_lib.dll", CallingConvention = CallingConvention.StdCall)]
static extern Byte getSomeStrings(IntPtr buffer, UInt64 size);

要从C#调用它,你应该这样做:

        IntPtr unmanagedBuffer = Marshal.AllocHGlobal(100);
        // Your Unmanaged Call
        getSomeStrings(unmanagedBbuffer, 100);
        string yourString = Marshal.PtrToStringUni(unmanagedBuffer);
        Marshal.FreeHGlobal(unmanagedBuffer);

如果您不希望应用中出现内存泄漏,请不要忘记致电FreeHGlobal。在“try / finally”子句中保护它很有意思。

答案 1 :(得分:0)

如果您想在托管方使用IntPtr,可以这样使用:

[DllImport("biosec_lib.dll", CallingConvention = CallingConvention.StdCall)]
static extern Byte getSomeStrings([In][Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] String[] providers, UInt64 count);