2012-08-10 62 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。显然,超载技巧不那么痛苦。