9

編集: これを 32 ビットで動作させたので、現在 64 ビットで動作させようとしています。DLL のソース コードを入手し、DLL とアプリケーションの両方を 64 ビット用にコンパイルしています。毎回アクセス違反になります。DLL コード ( Visual Studio 2005の C++ ) は次のとおりです。

#pragma pack( push, 2 )
// Output Results Structure
typedef struct tagTVA_RESULTS {
    int   iID;             /* Difference ID 1 .. n */
    int   iLeft;           /* Bounding rectangle */
    int   iRight;
    int   iTop;
    int   iBottom;
    double dCx;            /* Center of gravity */
    double dCy;
    double dMajor;         /* Shape information */
    double dMinor;
    double dAngle;         /* Rotational information */
    int    lArea;          /* Number of pixels */
    int    iEdge;          /* Set if difference is at the edge of the image */
    double dNormalDensity;
    int    iNormalCount;
    double dDifferenceDensity;
} TVA_RESULTS, *PTVA_RESULTS;
#pragma pack ( pop )

パックを 2 に設定していることに注意してください。アプリケーションでも 2 に設定しようとしましたが、失敗します。他の値を試してみましたが、同じではない値も試しました。4 を整数サイズとして、8 を double サイズとして明示的に使用してみました。しかし、私は (限られた知識で) 両方のパックのサイズが同じであれば、うまくいくはずだと思います。

この時点で、関数がどのように呼び出されるのか疑問に思っています。その最初のパラメーターは、これらの構造体の配列へのポインターです。アプリケーションは配列 ByRef の最初の要素を渡します。これにより、これが達成されると思います。しかし、配列への不適切なポインターがあると、症状が説明されます。DLL 内の関数定義は次のとおりです。

int WINAPI MNtvaAnalyzeVB (TVA_RESULTS *pResults, int iMaxCount)

私の上司は、ビッグ/リトルエンディアンの問題である可能性があると示唆しましたが、両方が同じ環境でコンパイルされている場合、それはありそうにありません。

私は何をすべきか?

編集終了 >>>


Visual Basic 6.0 アプリケーションを VB.NET に変換しています。外部 DLL ファイルに渡される構造がいくつかあります。これは機能していません。構造が正しく渡されていないことが原因だと感じています。

元の構造は次のとおりです。

Public Type TVA_PARAMETERS
    iStandardFilterOnOff As Long
    iSampleFilterOnOff As Long
    iDifferenceFilterOnOff As Long
    iRotationCorrectionOnOff As Long
    iLocalCorrectionOnOff As Long
    iStandardAOIx As Long
    iStandardAOIy As Long
    iStandardAOIdx As Long
    iStandardAOIdy As Long
    iSampleAOIx As Long
    iSampleAOIy As Long
    iSampleAOIdx As Long
    iSampleAOIdy As Long
    iRepeatHorizontal As Long
    iRepeatVertical As Long
    dSensitivity As Double
    iMergeWidth As Long
    iMergeHeight As Long
    iMinimumDifferenceArea As Long
    iMaximumDifferenceArea As Long
End Type

Visual Basic 6.0 でその型の変数に対して LenB を実行すると、84 バイトになります。(注:それがそのサイズを決定する有効な方法であるかどうかはわかりません。)

したがって、VB.NETに変換しようとしました:

Public Structure TVA_PARAMETERS
    Public iStandardFilterOnOff As Integer
    Public iSampleFilterOnOff As Integer
    Public iDifferenceFilterOnOff As Integer
    Public iRotationCorrectionOnOff As Integer
    Public iLocalCorrectionOnOff As Integer
    Public iStandardAOIx As Integer
    Public iStandardAOIy As Integer
    Public iStandardAOIdx As Integer
    Public iStandardAOIdy As Integer
    Public iSampleAOIx As Integer
    Public iSampleAOIy As Integer
    Public iSampleAOIdx As Integer
    Public iSampleAOIdy As Integer
    Public iRepeatHorizontal As Integer
    Public iRepeatVertical As Integer
    Public dSensitivity As Double
    Public iMergeWidth As Integer
    Public iMergeHeight As Integer
    Public iMinimumDifferenceArea As Integer
    Public iMaximumDifferenceArea As Integer
End Structure

VB.NET では、System.Runtime.InteropServices.Marshal.sizeof()は 88 バイトを提供します。これらは単なる数値であるため、これが機能することを望んでいました(文字列が面倒になる可能性があることはわかっています)。外部関数のコードはありませんが、次のように宣言されています。

Declare Function MNtvaParameters Lib "MNTva.dll" (ByRef pParameters As TVA_PARAMETERS) As Integer

この構造は同じサイズではないと推測しているため、DLL ファイルの呼び出しは失敗しますが、エラーは発生しません。また、前述のように、それを確認するためのコードもありません。成功した場合と同様にゼロを返しますが、実際には効果がないことは明らかです。

Runtime.InteropServices.StructLayoutAttributeで少し遊んでみましたが、それが答えであれば、正しいパラメーターを判断できません。

私はこのような別の構造を持っていますが、それはとても似ています。これを修正できれば、もう一方も修正できると思います。

4

2 に答える 2

8

もちろん、私が試した次のことは問題を解決しました。次のように構造を定義します。

<Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential, Pack:=1)> _
Public Structure TVA_PARAMETERS
  Public iStandardFilterOnOff As Integer
  ...
  etc.

問題を修正しました。

于 2012-11-13T01:58:28.117 に答える
3

良いリソースは次のとおりです。

Visual Basic 6.0の alongは 4 バイトで、これは VB.NET の整数である 32 ビットです。double は、VB.NET と Visual Basic 6.0 の両方で 8 バイトです (上記の記事によると)。VB.NET でも 84 バイトを取得します。

Option Strict On

Public Class Form1

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim A As New TVA_PARAMETERS
        MsgBox(A.ByteCount.ToString)
    End Sub

    Public Structure TVA_PARAMETERS
        Public iStandardFilterOnOff As Int32
        Public iSampleFilterOnOff As Int32
        Public iDifferenceFilterOnOff As Int32
        Public iRotationCorrectionOnOff As Int32
        Public iLocalCorrectionOnOff As Int32
        Public iStandardAOIx As Int32
        Public iStandardAOIy As Int32
        Public iStandardAOIdx As Int32
        Public iStandardAOIdy As Int32
        Public iSampleAOIx As Int32
        Public iSampleAOIy As Int32
        Public iSampleAOIdx As Int32
        Public iSampleAOIdy As Int32
        Public iRepeatHorizontal As Int32
        Public iRepeatVertical As Int32
        Public dSensitivity As Double
        Public iMergeWidth As Int32
        Public iMergeHeight As Int32
        Public iMinimumDifferenceArea As Int32
        Public iMaximumDifferenceArea As Int32

        Function ByteCount() As Integer
            Dim Results As New List(Of Byte)
            AddBytesToList(Results, BitConverter.GetBytes(iStandardFilterOnOff))
            AddBytesToList(Results, BitConverter.GetBytes(iSampleFilterOnOff))
            AddBytesToList(Results, BitConverter.GetBytes(iDifferenceFilterOnOff))
            AddBytesToList(Results, BitConverter.GetBytes(iRotationCorrectionOnOff))
            AddBytesToList(Results, BitConverter.GetBytes(iLocalCorrectionOnOff))
            AddBytesToList(Results, BitConverter.GetBytes(iStandardAOIx))
            AddBytesToList(Results, BitConverter.GetBytes(iStandardAOIy))
            AddBytesToList(Results, BitConverter.GetBytes(iStandardAOIdx))
            AddBytesToList(Results, BitConverter.GetBytes(iStandardAOIdy))
            AddBytesToList(Results, BitConverter.GetBytes(iSampleAOIx))
            AddBytesToList(Results, BitConverter.GetBytes(iSampleAOIy))
            AddBytesToList(Results, BitConverter.GetBytes(iSampleAOIdx))
            AddBytesToList(Results, BitConverter.GetBytes(iSampleAOIdy))
            AddBytesToList(Results, BitConverter.GetBytes(iRepeatHorizontal))
            AddBytesToList(Results, BitConverter.GetBytes(iRepeatVertical))
            AddBytesToList(Results, BitConverter.GetBytes(dSensitivity))
            AddBytesToList(Results, BitConverter.GetBytes(iMergeWidth))
            AddBytesToList(Results, BitConverter.GetBytes(iMergeHeight))
            AddBytesToList(Results, BitConverter.GetBytes(iMinimumDifferenceArea))
            AddBytesToList(Results, BitConverter.GetBytes(iMaximumDifferenceArea))
            Return Results.Count
        End Function

        Sub AddBytesToList(ByRef List As List(Of Byte), addBytes As Byte())
            For Each B As Byte In addBytes
                List.Add(B)
            Next

        End Sub
    End Structure

End Class
于 2012-12-11T08:44:05.107 に答える