2009-06-10 139 views
3

我正在處理一組通過動態分配數組返回數據的本機函數。這些函數將引用指針作爲輸入,然後將其指向結果數組。c#:通常將非託管陣列轉換爲託管列表

例如:

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()似乎沒有任何好處。

我錯過了什麼?有人能提出一個通用的方法來解決這個問題嗎

回答

2

你可以做一個合理的假設,所有指針的是大小和代表性是相同的(不知道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*當你調用該方法,但至少沒有重複代碼,否則。

0

你說:

Marshal.Copy()需要知道非託管數組的大小 。我只能用 確定這個使用不安全的代碼

看來你錯過了Marshal.SizeOf()

從你在帖子中提到的內容來看,這可能足以解決你的問題。 (另外,你的函數的參數可能需要對象**,而不是T **)

+0

Marshal.Copy需要知道源數組中有多少元素,但我不知道在編譯時由於數組是由本機代碼動態分配的。我不知道任何方式來確定非託管陣列中的元素數量,而不使用不安全的代碼。 – Odrade 2009-06-10 18:22:26