2

完全に機能している元の 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 モニターを使用して監視)。なぜこれが起こっているのですか、どうすれば修正できますか?

4

2 に答える 2

4

このコードはVB6で始まったようです。その言語では機能する可能性がありますが、今日は重大な問題です。[DllImport] の両方の宣言が間違っています。

ネイティブの HolderName() 関数に文字列の内容を変更させます。これは違法です。.NET の文字列は不変です。代わりに、引数を StringBuilder として宣言する必要があります。電話をかける前に、容量を十分に高く設定してください。これは危険な関数であることに注意してください。割り当てられた容量を超えて書き込むことを避けるように指示することはできません。

それが行われると、GC ヒープが破損し、デバッグするのが非常に厄介な問題になります。

Photo() の問題は、その引数が実際にはbyte[] であり、ref がないことです。偶然に働く傾向があり、非常に一般的な事故です。しかし、非常に大きな問題は、pinvoke マーシャラーが、配列を固定する必要があることを認識していないことです。Photo() の実行中にガベージ コレクターが実行されると、フロア マットが急に動き、配列が別の場所に移動します。Photo() は知らないため、古いアドレスを使用し続けます。

それが行われると、GC ヒープが破損し、デバッグするのが非常に厄介な問題になります。

それ以外の場合、VB.NET では機能するが C# では機能しないという素晴らしい理由はありません。より良い説明として、フレームワークの変更を疑っています。しかし、必要な出発点は確かにバグを排除することです。この種の破損の問題は、推論するのが非常に困難です.

于 2015-09-16T13:36:42.330 に答える
-1

最後に、私は自分の質問に答えました。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"));
于 2015-09-16T15:42:08.263 に答える