2012-11-13 12 views
8

EDIT: Avendo ottenuto che questo funzioni a 32 bit, ora sto cercando di farlo funzionare per 64 bit. Ho ottenuto il codice sorgente per la DLL e sia la DLL che l'applicazione sono state compilate per 64-bit. Ottengo una violazione di accesso ogni volta. Ecco il codice DLL (C++ in Visual Studio 2005):Convertire il tipo di Visual Basic 6.0 in "Struttura" VB.NET

#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) 

Nota è l'impostazione del pacchetto di 2. Ho provato impostandolo a 2 nella domanda, nonché, e non riesce. Ho provato altri valori e ho persino provato valori non uguali. Ho provato esplicitamente usando 4 come dimensione intera e 8 come dimensione doppia. Ma suppongo (con una conoscenza limitata) che se entrambe le dimensioni dei pacchi sono uguali, dovrebbe funzionare.

A questo punto, sospetto come viene chiamata la funzione. Il suo primo parametro è un puntatore a una matrice di queste strutture. L'applicazione passa nel primo elemento dell'array ByRef, che a mio parere lo realizza. Ma avere un cattivo puntatore all'array spiegherebbe i sintomi. Ecco la definizione della funzione nella DLL.

int WINAPI MNtvaAnalyzeVB (TVA_RESULTS *pResults, int iMaxCount) 

Il mio capo ha suggerito che potrebbe essere un problema big/little endian, ma che sembra improbabile, se sono entrambi di essere compilati nello stesso ambiente.

Cosa devo fare?

Fine modifica >>>


sto convertendo un'applicazione Visual Basic 6.0 a VB.NET. Ho un paio di strutture che vengono passate a file DLL esterni. Questo non funziona, e ho la sensazione che sia dovuto al fatto che le strutture non vengano passate correttamente.

Ecco la struttura originale:

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 

Se faccio un LenB su una variabile di quel tipo in Visual Basic 6.0, ottengo 84 byte. (NB: non sono sicuro se questo è un modo valido per determinare la sua dimensione.)

ho cercato di convertirlo in VB.NET così:

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 

In VB.NET, System.Runtime.InteropServices.Marshal.sizeof() dà 88 byte. Speravo dal momento che questi sono solo valori numerici che avrebbero funzionato (so che le corde possono essere un dolore). Non ho il codice per la funzione esterna, ma è dichiarato così:

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

Sto indovinando questa struttura non è la stessa dimensione, quindi la chiamata di file DLL non riesce, ma ottengo alcun errore, e come ho detto, non ho il codice per guardarlo. Restituisce uno zero, come dovrebbe, se ha successo, ma chiaramente non ha effettivamente un effetto.

Ho giocato un po 'con Runtime.InteropServices.StructLayoutAttribute, ma se questa è la risposta, non riesco a determinare i parametri corretti.

Ho un'altra struttura come questa, ma è molto simile. Immagino che se riuscirò a sistemare questo, sarò in grado di aggiustare l'altro.

+0

Non ho idea di cosa sia questa domanda, ma sembra interessante, quindi +1. :) – Neolisk

+1

@Neolisk: Probabilmente è "Ho un paio di strutture che vengono passate a DLL esterne. Questo non funziona". –

risposta

8

Beh, naturalmente la cosa successiva che ho provato ha risolto il problema. Definire la struttura in questo modo:

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

risolto il problema.

+0

Significa che .net ha allineato il doppio a un limite di 8 byte (prima di averlo corretto)? – xpda

+0

@xpda sì, probabilmente – MarkJ

+0

Beh, questo è quello che pensavo, ma l'altra struttura che ho menzionato aveva diverse variabili lunghe e 7 doppie. Sotto .NET, cambiando Longs to Integers, erano solo otto byte più lunghi. (Anche in questo caso, supponendo che le mie misurazioni della lunghezza siano valide.) Quindi non stava imbottendo tutti i doppi. Non sono sicuro di cosa stesse accadendo esattamente. Ma con LayoutKind.Sequential e Pack: = 1, si limita a posizionare ogni variabile nell'ordine elencato senza riempimento. –

2

Qui ci sono buone risorse:

vostra conversione sembra buono, un long in Visual Basic 6.0 è 4 byte che è 32 bit, che è un numero intero in VB.NET. I doppi sono 8 byte sia in VB.NET che in Visual Basic 6.0 (secondo gli articoli precedenti). Ottengo anche 84 byte in VB.NET.

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 
Problemi correlati