2016-08-01 24 views
1

なぜ誰が失敗しているのを見ることができますか?私が "IntPtr lpvObject"を "ref BITMAP lpvObject"に置き換えると、そのように動作させることができます。しかし、私はちょうどコードに間違って何かを見ることができません。Marshal.PtrToStructureアクセス違反

using System; 
using System.Runtime.InteropServices; 
using System.Drawing; 

namespace Program 
{ 
    class Core 
    { 
    [StructLayout(LayoutKind.Sequential)]  
    public struct BITMAP 
    { 
     public Int32 bmType; 
     public Int32 bmWidth; 
     public Int32 bmHeight; 
     public Int32 bmWidthBytes; 
     public UInt16 bmPlanes; 
     public UInt16 bmBitsPixel; 
     public IntPtr bmBits; 
    } 


    [DllImport("gdi32.dll", CharSet=CharSet.Auto, SetLastError=true)] 
     public static extern int GetObject (IntPtr hgdiobj, int cbBuffer, out IntPtr lpvObject); 


    static void Main(string[] args) 
    { 
     Bitmap TestBmp = new Bitmap (10, 10); 
     BITMAP BitmapStruct = new BITMAP(); 
     IntPtr pBitmapStruct, pBitmapStructSave; 
     int Status; 

     pBitmapStructSave = pBitmapStruct = Marshal.AllocHGlobal (Marshal.SizeOf(BitmapStruct)); 

     Status = GetObject (TestBmp.GetHbitmap(), Marshal.SizeOf (BitmapStruct), out pBitmapStruct); 

     Console.WriteLine ("\nBytes returned is " + Status + ", buffer address = " + pBitmapStruct); 

     try 
     { 
     BitmapStruct = (BITMAP) Marshal.PtrToStructure (pBitmapStruct, typeof(BITMAP)); 
     } 
     catch (Exception Ex) 
     { 
     Console.WriteLine (Ex.Message); 
     } 

     Marshal.FreeHGlobal(pBitmapStructSave); 
    } 
    } 
} 

出力は次のとおり

バイトが返さ32である、= 42949672960

未処理の例外バッファアドレス:System.AccessViolationExceptionは:保護されたメモリを読み書きしようとしました。これはしばしば、他のメモリが壊れていることを示します。 System.Runtime.InteropServices.Marshal.PtrToStructure(PTRのIntPtr、タイプstructureType)で

DにおけるProgram.Core.Main(文字列[]引数)で:\データプロジェクト\テスト\テスト\プログラム\ .cs:行41

+1

'out IntPtr lpvObject' - >' IntPtr lpvObject' – PetSerAl

+0

int GetObject(intPtr hgdiobj、int cbBuffer、out BITMAP lpobj)を使用します。簡単なピーシー。 –

+0

はい、私は述べたようにref BITMAPでも動作します。その問題は、関数がnullの3番目のパラメータを返すときに余分な処理が必要になることです。最も簡単な解決策は、ポインターを出力として引き続き使用します。いずれにせよ、私はIntPtr型が暗黙のうちであることを知る必要がありました。私は千年前にそれを推測していないでしょう。私はそれを検索しても見つけられませんでした。 – user118708

答えて

1

誤った署名を使用している可能性がありますか?

[DLLIMPORT( "GDI32.DLL")] 静的にextern int型のGetObject(のIntPtr HGDIOBJ、INT cbBuffer、のIntPtr lpvObject)。

http://www.pinvoke.net/default.aspx/gdi32/GetObject.html

また、アウト値はメソッド内で初期化しますが、すでにlpvObjectが定義されているので、それはおそらく起きていないことが必要であることを意味します。

+0

API仕様では、出力3番目のパラメータ:_Out_ LPVOID lpvObjectが指定されています。署名は問題ありません。プログラム出力は、outパラメータが期待どおりのポインタ値で返されることを示します。 – user118708

+0

OK、ありがとう。私は「外出」を取り除き、現在は機能しています。私は、outキーワードがどのように使われているかを再読しなければならない。 – user118708

+0

@ user118708 [例の使用方法](https://msdn.microsoft.com/en-us/library/windows/desktop/dd145119(v = vs.85).aspx)を参照するには、アドレスを渡す必要があります有効なバッファの値。私はなぜ文書にOUTとマークされているのかはわかりませんが、有効なオブジェクトが渡されている必要があります。 –