unsigned char *导致访问冲突异常

时间:2016-04-05 15:10:54

标签: c# c++ .net dll access-violation

我正在开发一个包装库,允许我的项目在任何CPU环境中使用x86 C ++ dll库,我无法控制dll因此我在C#中使用DllImport。

在C ++中声明了一个提供的函数:int __stdcall Func(int V,unsigned char * A) 并在VB中提供了一个示例声明:Private Declare Function Func Lib" lib.dll" Alias" _Func @ 8" (ByVal V As Long,A as Any)As Long

此函数将通过将Convert.ToInt64(decimalValue)作为V传递来请求设备向/从卡中添加/减去值,并在A中使用一些自定义信息。

以下是A:

的说明
  • 这是一个包含7个字节的字节指针。
  • 前5个字节用于存储将传递给卡片日志的信息(收据编号的最后4位数字应包含在前2个字节中,其他3个可以包含在A3A4A5中)
  • 最后2个字节用于存储将传递给设备的信息(收据号码的最后4位数字)
  • 返回时,A包含32字节数据。

经过数小时和数小时的研究和尝试,除了“访问违规例外”之外,我无法取得结果。请参阅以下草案代码:

[DllImport("lib.dll", EntryPoint="_Func@8")]
public static external Int64 Func(Int64 V, StringBuilder sb);

string ReceiptNum = "ABC1234";
decimal Amount = 10m;
byte[] A = new byte[32];
A[0] = Convert.ToByte(ReceiptNum.Substring(3, 2));
A[1] = Convert.ToByte(ReceiptNum.Substring(5));
A[2] = Convert.ToByte("A3");
A[3] = Convert.ToByte("A4");
A[4] = Convert.ToByte("A5");
A[5] = Convert.ToByte(ReceiptNum.Substring(3, 2));
A[6] = Convert.ToByte(ReceiptNum.Substring(5));
StringBuilder sb = new StringBuilder(
    new ASCIIEncoding().GetString(A), A.Length
);
Int64 Result = Func(Convert.ToInt64(Amount), sb);

此时它会抛出异常。我试过传递IntPtr,byte *,byte(by A [0]),byval,byref,但没有一个工作。 (试图部署为x86 CPU)

非常感谢任何帮助!谢谢你的时间!

PS - 使用StringBuilder的原因是库包含一个接受" char * Data"的函数。导致相同异常的参数,并且解决方案是使用StringBuilder作为指针传递,此函数的VB声明是:私有声明函数Func1 Lib" lib.dll" Alias" _Func1 @ 12(ByVal c As Byte,ByVal o As Byte,ByVal Data As String)As Long

2 个答案:

答案 0 :(得分:1)

您的外部定义错误。

StringBuilder是一个包含c#char数组的复杂结构。

c #chars是utf-16(具有用于解码unicode multichar caracters的复杂规则的双字节)。可能不是你想要的东西。

如果您的数据是原始字节缓冲区,则应该使用byte []

Int64也是c#long。

答案 1 :(得分:0)

好吧,您的原生方法签名需要int,而您正在尝试传递long long。这显然无法发挥作用。返回值也是如此。不要认为VB清楚地映射到VB.NET,更不用说C# - Long表示VB中的32位整数,但不是.NET。本机代码是一个非常复杂的环境,您在尝试与本机接口时更好地了解自己在做什么。

StringBuilder应仅用于字符数据。那不是你的情况,你应该使用byte[]代替。无论你正在做什么有趣的事情,你都试图传递无效的unicode数据而不是原始字节。混淆可能是因为C不区分byte[]string - 两者通常都表示为char*

此外,我不认为你期望这个包装器在AnyCPU环境中工作。如果本机DLL是32位,则只能从32位进程使用它。 AnyCPU并不神奇,它只是将bit-ness的决定推迟到运行时,而不是编译时。