我正在开发一个包装库,允许我的项目在任何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:
的说明经过数小时和数小时的研究和尝试,除了“访问违规例外”之外,我无法取得结果。请参阅以下草案代码:
[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
答案 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的决定推迟到运行时,而不是编译时。