我处理的一组通过动态分配的阵列返回数据本地函数。该函数采用一个参考指针作为输入,然后将其指向所得阵列。

例如:

typedef struct result
{
   //..Some Members..//
}

int extern WINAPI getInfo(result**);

呼叫后,“结果”指向结果的空终止阵列*。

我想创建从该非托管阵列的管理列表。我可以执行以下操作:

struct Result
{
   //..The Same Members..//
}

public static unsafe List<Result> getManagedResultList(Result** unmanagedArray)
{
    List<Result> resultList = new List<Result>();

    while (*unmanagedArray != null)
    {
       resultList.Add(**unmanagedArray);
       ++unmanaged;
    }
    return result;
}

这工作,这将是乏味和丑陋重新实现每种类型结构的,我将不得不处理(〜35)。我想一个解决方案,已经过去结构的阵列中的类型通用的。为此,我想:

public static unsafe List<T> unmanagedArrToList<T>(T** unmanagedArray)
{ 
    List<T> result = new List<T>();
    while (*unmanagedArray != null)
    {
        result.Add((**unmanagedArray));
        ++unmanagedArray;
    }
    return result;
}

但是,这不会编译,因为你不能“取的地址,获得的大小,或声明指针到托管类型(‘T’)”。

我也试图做到这一点,而无需使用不安全的代码,但我跑成Marshal.Copy()需要知道的非托管数组的大小的问题。我只能确定此使用不安全的代码,因此似乎是没有好处在这种情况下使用Marshal.Copy()。

我在想什么?可能有人提出一个通用的办法解决这个问题?

有帮助吗?

解决方案

您可以做一个合理的假设,所有指针的是大小和代表性是相同的(不知道C#规格保证了这一点,但在实践中,你会发现它是如此)。所以,你可以把你的T**IntPtr*。另外,我看不出Marshal.Copy将如何帮助你在这里,因为它仅具有内置类型的重载。所以:

public static unsafe List<T> unmanagedArrToList<T>(IntPtr* p)
{ 
    List<T> result = new List<T>();
    for (; *p != null; ++p)
    {
        T item = (T)Marshal.PtrToStructure(*p, typeof(T));
        result.Add(item);
    }
    return result;
}

当然,你需要有明确的转换,只要你把这个给IntPtr*,但至少没有重复代码,否则。

其他提示

您表示:

  

Marshal.Copy()需要知道大小   非托管阵列。我只能   确定这一点使用不安全的代码

看来你错过 Marshal.SizeOf()

这是你在帖子中提到的东西,这可能足以解决你的问题。 (另外,你的函数的参数可能需要对象**代替T **)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top