2016-08-01 230 views
1

任何人都可以看到它爲什麼失敗?如果我用「ref BITMAP lpvObject」替換「out IntPtr 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(IntPtr的PTR,類型structureType)

在Program.Core.Main(字串[] args)在d:\數據\項目\測試\測試\程序.cs:line 41

+1

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

+0

使用int GetObject(IntPtr hgdiobj,int cbBuffer,out BITMAP lpobj)。十分簡單。 –

+0

是的,它也適用於參考BITMAP,如我所述。這樣做的麻煩是當函數返回一個空的第三個參數時需要額外的處理。最簡單的解決方案仍然是將指針作爲輸出。無論如何,我需要知道IntPtr類型是一個隱式輸出。我不會在一千年內猜出它。我也不會從搜索中找到它。 – user118708

回答

1

難道是因爲您使用了錯誤的簽名嗎?

[DllImport(「gdi32.dll」)] static extern int GetObject(IntPtr hgdiobj,int cbBuffer,IntPtr lpvObject);

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

此外,意味着,值需要在方法中被初始化,並且很可能不會發生,因爲你已經有了lpvObject定義。

+0

API規範聲明瞭輸出第三個參數:_Out_ LPVOID lpvObject。所以簽名很好。程序輸出表明out參數按照預期返回一個指針值。 – user118708

+0

好的,謝謝。我刪除了「出」,現在它正在工作。我必須重新閱讀out關鍵字的使用方式。 – user118708

+0

@ user118708看[示例用法](https://msdn.microsoft.com/en-us/library/windows/desktop/dd145119(v = vs.85).aspx),您需要傳入地址有效的緩衝區。我不知道它爲什麼在文檔中標記爲OUT,但它肯定需要一個通過的有效對象 –