转换自VB.NET转换为c# -没有正确返回值

本文关键字:转换 返回值 VB NET | 更新日期: 2023-09-27 18:13:10

原来的VB.net,这是完美的工作:

Declare Function HolderName Lib "myCard.dll" (ByVal buf As String) As Integer
Declare Function Photo Lib "myCard.dll" (ByRef photo As Byte) As Integer
...
buff = Space(200) : res = HolderName(buff)
ShowMsg("HolderName():" & IIf(res = 0, "OK:" & Trim(buff), "FAIL"))
photobuf = New Byte(4096) {}
res = Photo(photobuf(0))
ShowMsg("Photo():" & IIf(res = 0, "OK", "FAIL"))
If res = 0 Then
    Dim ms As New MemoryStream(photobuf)
    picImage.Image = Image.FromStream(ms)
End If

c#中转换后的代码(使用http://converter.telerik.com/)

using System.Runtime.InteropServices;
...
[DllImport("myCard.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int HolderName(String dBuff);
[DllImport("myCard.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
public static extern int Photo(ref byte photo);
//...
buff = new String(' ', 200);
res = HolderName(buff);
// buff remains UNALTERED!
ShowMsg("HolderName():" + (res == 0 ? "OK:" + Strings.Trim(buff) : "FAIL"));
photobuf = new byte[4096];
res = Photo(ref photobuf[0]);
ShowMsg("Photo():" + (res == 0 ? "OK" : "FAIL"));
// photobuf successfully receives the data bytes from Photo function
if (res == 0)
{
    MemoryStream ms = new MemoryStream(photobuf);
    picImage.Image = Image.FromStream(ms);
}

问题是buff保持不变,即使HolderName函数实际上返回一些值(使用USB监视器观看)。为什么会发生这种情况,我该如何解决?

转换自VB.NET转换为c# -没有正确返回值

看起来这段代码是从VB6开始的。它可以在那种语言中工作,但今天遇到了严重的麻烦。两个[DllImport]声明都是错误的。

让本地的HolderName()函数修改字符串的内容。这是非法的,。net中的字符串是不可变的。必须将参数声明为StringBuilder。在你打电话之前,把它的容量设置得足够高。注意,这是一个有风险的函数,您不能告诉它以避免超出已分配容量的写入。

当它这样做时,它会破坏GC堆,这是一个非常讨厌的调试问题。

Photo()的问题是,它的参数是实际上是 byte[],而不是ref.倾向于意外地工作,这是一个非常常见的意外。但最大的问题是,pinvoke编组程序不知道数组需要固定。当垃圾收集器在Photo()运行时运行时,它将抖动地垫并将数组移动到其他地方。照片()不知道,一直用旧地址。

当它这样做时,它会破坏GC堆,这是一个非常讨厌的调试问题。

否则就没有什么奇妙的理由说明为什么它能在VB中工作。. NET,而不是c#。我认为框架的改变是一个更好的解释。但是一个必要的出发点当然是消除bug,这类损坏问题很难通过推理来解决。

最后,我回答了自己的问题。StringBuilder就是答案!这是代码…

        [DllImport("mykaddll.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        public static extern int HolderName([Out] StringBuilder dBuff);
        //....
        StringBuilder sbBuff = new StringBuilder(200);
        res = HolderName(sbBuff);
        buf = sbBuff.ToString().Trim();
        ShowMsg("HolderName():" + (res == 0 ? "OK:" + buf : "FAIL"));