c# Marshal 以 null 结尾的字符串数组

Posted

技术标签:

【中文标题】c# Marshal 以 null 结尾的字符串数组【英文标题】:c# Marshal null-terminated string array 【发布时间】:2017-11-10 23:14:58 【问题描述】:

我正在尝试导入以下内容:

const char * const *object_get_prop_names(propobject_t *ocr);

作为:

[DllImport("vender.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern IntPtr object_get_prop_names(int* osr);

基于:https://limbioliong.wordpress.com/2011/08/14/returning-an-array-of-strings-from-c-to-c-part-1/

我尝试了以下方法:

var pNames = object_get_prop_names(hdl);

int StringCount = 200; //how do I know string count?

IntPtr[] pIntPtrArray = new IntPtr[StringCount];
ManagedStringArray = new string[StringCount];

Marshal.Copy(pNames, pIntPtrArray, 0, StringCount);

for (int i = 0; i < StringCount; i++)

    ManagedStringArray[i] = Marshal.PtrToStringAnsi(pIntPtrArray[i]);
    //Marshal.FreeCoTaskMem(pIntPtrArray[i]); crashes


//Marshal.FreeCoTaskMem(pUnmanagedStringArray); crashes

这可行,但我猜我有内存泄漏并访问我不应该访问的内存。

我应该如何释放内存?

我怎么知道计数?这是来自供应商的,他们不会为小我修改 dll。 :)

也请原谅我钻研一些我知之甚少的东西。

【问题讨论】:

它返回 const char* 所以没有太多理由担心释放字符串。必须有 some 种方法来找出有多少字符串。我会寻找 IntPtr.Zero 或空字符串。在您知道之前,您不能安全地使用 Marshal.Copy(),对每个元素使用 Marshal.ReadIntPtr(),每次将 pNames 递增 IntPtr.Size。 @Hans 成功了!我读到我得到一个空值。你能写出解决方案,以便我给你功劳吗? 【参考方案1】:

按照汉斯的建议:

var pNames = object_get_prop_names(hdl);
if (h == IntPtr.Zero)

    return null;


var nameList = new List<string>();
int elementSize = Marshal.SizeOf(typeof(IntPtr));

for (int i = 0; i < 200; i++) //don't know length, pick large number

    var ptr = Marshal.ReadIntPtr(pNames, i * elementSize);
    var str = Marshal.PtrToStringAnsi(ptr);
    if (!string.IsNullOrWhiteSpace(str))
    
        nameList.Add(str);
    
    else //end of pNames
     
        break; 
    

效果很好。我无法知道有多少属性名称,所以我只需要选择一个比可能的属性名称数量更大​​的数字。

【讨论】:

以上是关于c# Marshal 以 null 结尾的字符串数组的主要内容,如果未能解决你的问题,请参考以下文章

我可以检查一个字符串是不是以 null 结尾,但不能检查它是不是还没有以 null 结尾

C# Marshal类基本概念和入门示例程序

使用OpenSSL内存BIO以正确的方式写入和读取以null结尾的字符串

C# Marshal

C# Marshal

c#中Marshal.Copy()方法的使用