2012-08-10 192 views
1

C函數我怎麼能跳過C#中的可選參數(pioRecvPci)時,如何處理可選參數結構? 我認爲主要問題是,在C中的參數是一個指針,以便能夠一邊在C#上的結構ref關鍵字使用可以不通過定義空供應NULL。調用從C#

C代碼

typedef struct { 
    DWORD dwProtocol; 
    DWORD cbPciLength; 
} SCARD_IO_REQUEST; 

LONG WINAPI SCardTransmit(
     __in   SCARDHANDLE hCard, 
     __in   LPCSCARD_IO_REQUEST pioSendPci, 
     __in   LPCBYTE pbSendBuffer, 
     __in   DWORD cbSendLength, 
     __inout_opt LPSCARD_IO_REQUEST pioRecvPci, 
     __out  LPBYTE pbRecvBuffer, 
     __inout  LPDWORD pcbRecvLength 
    ); 

C#代碼

[StructLayout(LayoutKind.Sequential)] 
public struct SCARD_IO_REQUEST 
{ 
    public int dwProtocol; 
    public int cbPciLength; 
} 

[DllImport("winscard.dll")] 
public static extern int SCardTransmit(
    int hCard, 
    ref SCARD_IO_REQUEST pioSendRequest, 
    ref byte SendBuff, 
    int SendBuffLen, 
    ref SCARD_IO_REQUEST pioRecvRequest, 
    ref byte RecvBuff, 
    ref int RecvBuffLen); 
+0

你可以使用'class'而不是(我依稀記得以前使用這種方法成功很長,很長一段時間)。或者,它可能會將參數聲明爲「SCARD_IO_REQUEST?」,但這只是一個瘋狂的猜測。 – 2012-08-10 12:22:21

回答

3

您可以更改structclass,然後通過null。請記住,C#struct是從C++ struct完全不同的,在這裏你真的想用一個C#class

或者,如果你總是想忽略pioRecvRequest更改SCardTransmit的簽名,以便pioRecvRequest的類型IntPtr。然後通過IntPtr.Zero的值。

其實,SCARD_IO_REQUEST只是一個標題,如果你想將它傳遞的通話,你將不得不管理這個結構和額外的緩衝空間,自己反正所以IntPtr是正確的選擇。然後,您必須使用Marshal函數在呼叫之前分配和填充結構,並在呼叫之後解組並釋放數據。

3

C#支持方法重載。你可以利用這裏的東西,重新聲明該方法,但現在給它一個IntPtr參數類型(無參考)。並通過IntPtr.Zero。

第二種方式是自己封的結構。聲明參數類型IntPtr。然後使用Marshal.AllocHGlobal()爲結構分配內存,Marshal.StructureToPtr()將結構複製到結構中。調用後的Marshal.FreeHGlobal()。或者通過IntPtr.Zero。顯然,超載技巧不那麼痛苦。