C#调用c++的动态库,提示约定和参数问题

在写一个接口,调用设备读取银行卡信息,调用的是一个读卡器提供的dll。
接口文档如下:

```c++
int __stdcall ReadPBOCGenARQC(char *Field2, char *Field35, char *Field36,char * ARQC, char *ErrMsg);
接口描述:
        该接口不是立刻返回,循环读卡,流程请参考指令扫码流程 ,超时时间30秒。
入参:    无
出参:    
Field2:银联2域数据,数据转换为ASCII(主账号)
        Field35:银联35域数据,数据转换为ASCII
Field36:银联36域数据,数据转换为ASCII
ARQC:银联55域数据,数据转换为ASCII
返回: 0成功 非零失败
错误:ErrMsg(补充错误信息)
我的代码:

```c#
[DllImport("HealthyCarder.dll", EntryPoint = "ReadPBOCGenARQC", CallingConvention = CallingConvention.Cdecl)]
        public static extern int ReadPBOCGenARQC(StringBuilder Field2, StringBuilder Field35, StringBuilder Field36, StringBuilder ARQC, StringBuilder ErrMsg);
      

运行的时候提示:其他信息: 对 PInvoke 函数“WqReadCard!WqReadCard.clsReadCard::ReadPBOCGenARQC”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。
CallingConvention = CallingConvention.Cdecl 这段加不加,都报错。麻烦帮忙看看,指导一下。。谢谢

C#对应char*的数据类型是IntPtr啊

明明是stdcall,你加上 cdecl 干嘛
CallingConvention = CallingConvention.Stdcall 看看

【以下回答由 GPT 生成】

这个问题可能是因为C#代码中的PInvoke签名与C++动态库中的函数签名不匹配导致的。根据接口描述中的信息,我们可以看到接口是以__stdcall调用约定被声明的,而C#默认使用的是__cdecl调用约定。此外,C++的char *类型在C#中应该使用StringBuilder来代替。

为了解决这个问题,可以尝试以下步骤:

  1. 将C#中的PInvoke签名更改为与C++函数签名相匹配:
[DllImport("HealthyCarder.dll", EntryPoint = "ReadPBOCGenARQC", CallingConvention = CallingConvention.StdCall)]
public static extern int ReadPBOCGenARQC(StringBuilder Field2, StringBuilder Field35, StringBuilder Field36, StringBuilder ARQC, StringBuilder ErrMsg);
  1. 在调用之前,将StringBuilder的实例化大小设置为足够大的空间来存储返回的字符串。例如,假设每个字段的最大长度为1000,可以使用:
StringBuilder Field2 = new StringBuilder(1000);
StringBuilder Field35 = new StringBuilder(1000);
StringBuilder Field36 = new StringBuilder(1000);
StringBuilder ARQC = new StringBuilder(1000);
StringBuilder ErrMsg = new StringBuilder(1000);
  1. 调用接口函数并进行循环读卡,直到超时或成功为止:
int result = ReadPBOCGenARQC(Field2, Field35, Field36, ARQC, ErrMsg);

// 设置超时时间,单位为毫秒
int timeout = 30000;

// 获取当前时间的毫秒数
int startTime = Environment.TickCount;

while (result != 0 && (Environment.TickCount - startTime) < timeout)
{
    // 继续读卡操作
    result = ReadPBOCGenARQC(Field2, Field35, Field36, ARQC, ErrMsg);
}

if (result == 0)
{
    // 成功读取银行卡信息
    string field2 = Field2.ToString();
    string field35 = Field35.ToString();
    string field36 = Field36.ToString();
    string arqc = ARQC.ToString();
}
else
{
    // 读卡失败,查看错误信息
    string errMsg = ErrMsg.ToString();
}

通过以上步骤,我们尝试将C#的PInvoke签名与C++函数签名匹配,并在调用接口时进行循环读卡操作,直到超时或成功读取到银行卡信息为止。希望这些步骤能够帮助你解决问题。如果问题仍然存在,请回复告知详细情况。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^