2009-06-10 8 views
3

私は、動的に割り当てられた配列を通してデータを返すネイティブ関数のセットを扱っています。関数は参照ポインタを入力として受け取り、結果の配列を参照します。例えばc#:アンマネージ配列を管理リストに一般的に変換する

:呼び出し後

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

int extern WINAPI getInfo(result**); 

、 '結果が' *結果のNULLで終了する配列を指します。

このアンマネージ配列から管理対象リストを作成したいとします。私は次の操作を行うことができます。

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

すべてのポインタのサイズと表現が同じであることを妥当に仮定することができます実際にはあなたはそれが事実であると分かります)。だから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 **ではなくObject **でなければならないかもしれません。)

+0

Marshal.Copyはソース配列内の要素数を知る必要がありますが、配列がネイティブコードによって動的に割り当てられるため、コンパイル時にはわかりません。安全でないコードを使用しないで、アンマネージド配列内の要素の数を判断する方法はわかりません。 – Odrade

+0

また、オブジェクトはマネージ型です。上記のように、管理された型では安全でない操作は実行できません。 – Odrade

+0

最悪の場合、関数のパラメータにIntPtrを使用し、最後に到達するまで配列の各要素に対してMarshal.Copy()を1回呼び出します。マーシャリングを使用して、渡されたIntPtrのコピーを作成することで、これをショートカットすることができます。SizeOf()を使用して、ヌル・エントリを見つけるまでそのサイズをループ内に追加するよりも、正しいサイズを決定してください。 –

関連する問題