6

C#でbyte[]からIntPtrを取得する方法を参照する

IntPtrが参照しているデータをバイト[]に読み込んでから、別のIntPtrに戻そうとしています。ポインターはスキャナーデバイスからキャプチャされた画像を参照しているため、この情報のキャプチャはバイト配列に配置する必要があると仮定しました。

また、Marshal.SizeOf()メソッドが、IntPtrが参照しているデータのサイズを返すのか、ポインター自体のサイズを返すのかはわかりません。

私の問題は、「タイプ'System.Byte[]'をアンマネージ構造としてマーシャリングできません。意味のあるサイズまたはオフセットを計算できません」というエラーが表示されることです。

IntPtr bmpptr = Twain.GlobalLock (hImage);

try
{
     byte[] _imageTemp = new byte[Marshal.SizeOf(bmpptr)];
     Marshal.Copy(bmpptr, _imageTemp, 0, Marshal.SizeOf(bmpptr));

     IntPtr unmanagedPointer = Marshal.AllocHGlobal(
         Marshal.SizeOf(_imageTemp));

     try
     {
           Marshal.Copy(_imageTemp, 0, unmanagedPointer, 
               Marshal.SizeOf(_imageTemp));

           Gdip.SaveDIBAs(
               string.Format("{0}\\{1}.{2}", CaptureFolder, "Test", "jpg"), 
               unmanagedPointer, false);
     }
     finally
     {
           Marshal.FreeHGlobal(unmanagedPointer);
     }
}
catch (Exception e)
{
      Scanner.control.Test = e.Message;
}
4

2 に答える 2

7

toの呼び出しによってスローされた例外SizeOfは正しいです。このメソッドには、渡す配列の長さを知る方法がなく、ポインターがあるだけです。

Copyそのために、データを取得する最も簡単な方法は、Marshalクラスの静的メソッドを呼び出し、アンマネージデータへのポインター、読み取るバイトのインデックスと数、および事前に割り当てられたバイトのバッファーをに渡すことです。データをにマーシャリングします。

配列のサイズを取得することに関しては、 Anton Tykhyyがコメントで指摘しているように、への呼び出しはによって割り当てられたメモリを使用しているように見えます(ここでは非常に注意してください)。つまり、 P/レイヤーを呼び出してサイズを取得します。Twain.GlobalLock(hImage)GlobalAllocGlobalSize

の呼び出しによって割り当てられたものへのハンドルでない場合は、モジュールがメモリをGlobalAllocどのように割り当てているかを調べ、適切なメカニズムを使用して、が指すメモリの長さを決定する必要があります。TwainIntPtr

于 2010-12-08T16:18:37.177 に答える
2

1-私bmpptrはすでにアンマネージポインターであると思いますが、もしそうなら、なぜこれをアンマネージポインターに「ラウンドトリップ」する必要があるのunmanagedPointerですか?

2- Marshal.SizeOfは、アンマネージメモリ割り当てのサイズを提供しません。

Marshal.Copyを使用すると、アンマネージメモリの内容をマネージバイト配列にコピーできますが、アンマネージバッファからマネージバッファに移動する必要のあるバイト数を知る必要があります。APIは、理想的にはこの情報を提供する必要があります。

于 2010-12-08T16:17:22.350 に答える