unsigned char* 导致访问冲突异常

unsigned char* causes Access Violation Exception

我正在开发一个包装库,允许我的项目在任何 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 中的一些自定义信息来请求设备 Add/Deduct 值 to/from 卡片。

这里是A的描述:

经过数小时的研究和尝试,除了 'Access Violation Exception',我无法做出其他结果。请看下面的草稿代码:

[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 和 none 它们都有效。 (也尝试部署为 x86 CPU)

非常感谢任何帮助!感谢您的宝贵时间!


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

好吧,您的本机方法签名采用 int,而您正在尝试传递 long long。那是行不通的,很明显。 return 值也是如此。不要假设 VB 清楚地映射到 VB.NET,更不用说 C# - Long 在 VB 中表示 32 位整数,但在 .NET 中不是。本机代码是一个非常复杂的环境,在尝试与本机交互时,您最好知道自己在做什么。

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

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

你的外部定义有误

StringBuilder 是一个包含 C# 字符数组的复杂结构。

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

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

Int64 也是 c# long。