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()を使用することに何ら利益をはないと思われたので、私は、この使用して、安全でないコードを決定することができる。
私は何をしないのですか?誰かがこの問題への一般的なアプローチを提案してもらえますか?
解決
あなたはサイズとすべてのポインタの表現は(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のオブジェクトである必要があります。)