1

如何跳过 C# 中的可选参数 (pioRecvPci)?我认为主要问题是在 C 中参数是一个指针,因此可以提供 NULL 而在 C# 中使用结构上的 ref 关键字,根据定义不能为空。

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);
4

2 回答 2

3

您可以将 更改struct为 aclass然后通过null。请记住, C#struct与 C++ 完全不同struct,在这里您真的想使用 C# class

或者,如果您总是想忽略pioRecvRequest更改SCardTransmitsopioRecvRequest类型的签名IntPtr。然后传递IntPtr.Zero值。

实际上,这SCARD_IO_REQUEST只是一个标头,如果你想在调用中传递它,你将不得不自己管理这个结构和额外的缓冲区空间,所以这IntPtr是正确的选择。然后,您必须在调用之前使用Marshal函数来分配和填充结构,并在调用之后解组数据并释放它。

于 2012-08-10T12:21:19.147 回答
3

C# 支持方法重载。您可以在这里利用一些东西,重新声明该方法,但现在给它一个 IntPtr 参数类型(无 ref)。并通过 IntPtr.Zero。

第二种方法是自己编组结构。声明参数类型 IntPtr。并使用 Marshal.AllocHGlobal() 为结构分配内存, Marshal.StructureToPtr() 将结构复制到其中。Marshal.FreeHGlobal() 通话后。或者通过 IntPtr.Zero。显然,超载技巧的痛苦要小得多。

于 2012-08-10T13:14:18.000 回答