c# - 从 C# 调用 C 函数时如何处理可选结构参数

标签 c# c winscard

<分区>

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

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

最佳答案

您可以将struct 更改为class,然后传递null。请记住,C# struct 与 C++ struct 有很大不同,在这里您真的想使用 C# class

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

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

关于c# - 从 C# 调用 C 函数时如何处理可选结构参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11901534/

相关文章:

windows - 如何在Windows 8中正确使用SCardGetStatusChange?

Windows 7 SCardGetStatusChange 中的 C++ 源代码返回代码 6

c# - 如何强制以父类(super class)形式放置控件?

c# - 只读 Dictionary<int, List<int>>

c# - UI 线程 vs 后台线程 - UI 控制可访问性边界

c - 修改存在缓冲区溢出漏洞的C函数的返回地址

C编译: relocation truncated to fit R_X86_64_PC32 against symbol

c++ - 如何读取智能卡上的用户数据?

c# - 可写位图构造函数崩溃

c - 在 C 中将 sqrt 定义为 int 类型?