4

我以前见过试图读取或写入受保护的内存错误。通常,当我没有正确设置 c# 结构时会出现错误。我确实有其他电话正常工作,但这个电话不合作。我几乎可以肯定它可能是我的函数调用和导致问题的结构。

C 语法

int CardTransaction(pTRequest req, char *ProductCodes)

请求结构(我把它浓缩成 b/c 有重复的数据类型)

typedef struct _cardRequest
{
  unsigned short RedemptionNum
  long TotalAmount;
  unsigned char filler1[257];
  char CardNumber[80];
  unsigned char cardType;
} TRequest, *pTRequest;

C# 函数调用

[DllImport("card.dll"), CallingConvention.Cdecl, CharSet = CharSet.Auto)]
public static extern int CardTransaction(ref CardRequest cardRequest, [MarshalAs(UnManagedType.LPStr)] StringBuilder productCodes);

ProductCodes 为空,所以我只是实例化了一个没有任何内容的 stringbuilder 对象并将其传递。这是我认为可能有问题的一个地方。

C#结构

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]    
public struct CardRequest
{
  public uint16 RedemptionNum

  public int TotalAmount;

  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
  public string filler1;

  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
  public string CardNumber;

  public byte cardType;

} 
4

1 回答 1

2

明显的问题是 C 代码使用对齐的结构,但由于某种原因,您选择打包 C# 结构。从 C# 代码中删除Pack = 1以使两个结构匹配。

除此之外,填充数组看起来更像是字节数组而不是字符串。我会这样声明:

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 257)]
public byte[] filler1;

如果你想传递nullproductCodes参数,那么我希望你能做到这一点。我自己不记得每次都这样做,但通常当您传递null给 ap/invoke 时,编组器将传递NULL给本机代码。

于 2013-10-08T23:51:51.563 回答