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

时间:2017-11-10 23:14:59

标签: c# c++ marshalling dllimport

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

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。 :)

也请原谅我钻研我所知甚少的事情。

1 个答案:

答案 0 :(得分: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; 
    }
}

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