2013-11-26 126 views
0

我一直在隨機獲取訪問衝突異常時調用PInvoke,結構版本似乎工作。類版本將隨機給我訪問衝突異常。我在類版本和結構版本中有額外字段的問題與合同期望的內容完全匹配嗎?我會假設額外的領域應該不重要,因爲非託管代碼應該只能訪問前3個UInt32的。C#PInvoke結構與類訪問衝突

我害怕的是訪問衝突問題仍然存在與結構版本,但不是經常。

任何幫助,將不勝感激 感謝

[StructLayout(LayoutKind.Sequential)] 
public class TStat 
{ 
    private UInt32 bitfield; 
    public UInt32 cbInQue; 
    public UInt32 cbOutQue; 
    private readonly UInt32 fCtsHoldMask = 0x00000001; 
    private readonly Int32 fCtsHoldShift = 0; 
    private readonly UInt32 fDsrHoldMask = 0x00000002; 
    private readonly Int32 fDsrHoldShift = 1; 
    private readonly UInt32 fRlsdHoldMask = 0x00000004; 
    private readonly Int32 fRlsdHoldShift = 2; 
    private readonly UInt32 fXoffHoldMask = 0x00000008; 
    private readonly Int32 fXoffHoldShift = 3; 
    private readonly UInt32 fXoffSentMask = 0x00000010; 
    private readonly Int32 fXoffSentShift = 4; 
    private readonly UInt32 fEofMask = 0x00000020; 
    private readonly Int32 fEofShift = 5; 
    private readonly UInt32 fTximMask = 0x00000040; 
    private readonly Int32 fTximShift = 6; 

    public bool fCtsHold 
    { 
     get { return ((bitfield & fCtsHoldMask) != 0); } 
     set { bitfield |= (Convert.ToUInt32(value) << fCtsHoldShift); } 
    } 
    public bool fDsrHold 
    { 
     get { return ((bitfield & fDsrHoldMask) != 0); } 
     set { bitfield |= (Convert.ToUInt32(value) << fDsrHoldShift); } 
    } 
    public bool fRlsdHold 
    { 
     get { return ((bitfield & fRlsdHoldMask) != 0); } 
     set { bitfield |= (Convert.ToUInt32(value) << fRlsdHoldShift); } 
    } 
    public bool fXoffHold 
    { 
     get { return ((bitfield & fXoffHoldMask) != 0); } 
     set { bitfield |= (Convert.ToUInt32(value) << fXoffHoldShift); } 
    } 
    public bool fXoffSent 
    { 
     get { return ((bitfield & fXoffSentMask) != 0); } 
     set { bitfield |= (Convert.ToUInt32(value) << fXoffSentShift); } 
    } 
    public bool fEof 
    { 
     get { return ((bitfield & fEofMask) != 0); } 
     set { bitfield |= (Convert.ToUInt32(value) << fEofShift); } 
    } 
    public bool fTxim 
    { 
     get { return ((bitfield & fTximMask) != 0); } 
     set { bitfield |= (Convert.ToUInt32(value) << fTximShift); } 
    } 
} 

[StructLayout(LayoutKind.Sequential)] 
public struct TStat 
{ 
    private UInt32 bitfield; 
    public UInt32 cbInQue; 
    public UInt32 cbOutQue; 
} 
[DllImport("coredll.dll", EntryPoint = "ClearCommError", SetLastError = true)] 
    private static extern Boolean ClearCommError(IntPtr hPort, out UInt32 Errors, out TStat Stat); 

PInvoke的鏈接:

_http://www.pinvoke.net/default.aspx/kernel32.clearcommerror _http://www.pinvoke .NET/Default.aspx的/結構/ COMSTAT.html

原住民從MSDN

簽名

BOOL WINAPI ClearCommError(
_In_  HANDLE hFile, 
_Out_opt_ LPDWORD lpErrors, 
_Out_opt_ LPCOMSTAT lpStat 
); 

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363200(v=vs.85).aspx

typedef struct _COMSTAT { 
DWORD fCtsHold :1; 
DWORD fDsrHold :1; 
DWORD fRlsdHold :1; 
DWORD fXoffHold :1; 
DWORD fXoffSent :1; 
DWORD fEof :1; 
DWORD fTxim :1; 
DWORD fReserved :25; 
DWORD cbInQue; 
DWORD cbOutQue; 
} COMSTAT, *LPCOMSTAT; 
+0

您可以顯示接口的另一側,非託管方 –

+0

我加入了PInvoke的聯繫,以及從MSDN的結構的def從msdn的非託管呼叫定義以及 – user3037658

回答

3

當您在的PInvoke簽名它是作爲一個指針值基本上是通過使用class類型。 ref/out也是如此。因此out TStatTStatclass是通過雙指針傳遞值。只有原始參數類型爲TStat**纔有意義。

我猜測,本機簽名實際上是TStat*。這就是爲什麼作爲一個struct作品PInvoke的傳球,因爲out struct具有相同的數據的語義TStat*

+0

這不會導致方法調用永不工作?它似乎大部分時間都在返回,並且它的數據似乎與我期待的數據一致cbInQue – user3037658

+0

無法保證獲得AV,指針有指向可寫內存的訣竅。 cbInQue具有很好的價值很難解釋,除了它通常應該是0並不難。但它顯然是錯誤的,請使用[Out]而不是* out *。 –

+0

感謝您的幫助 – user3037658