Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 13
  1. #1
    Utente di HTML.it L'avatar di ganesha
    Registrato dal
    Jan 2003
    Messaggi
    357

    [VB6] spacchettare un messagio

    mi scuso per il titolo delle discussione, ma veramente non sapevo che scriverci

    sto scrivendo un'aaplicazione in VB6 che legge, tramite un protocollo, dei messaggi provenienti da un server (scritto in C).
    quando arriva un messaggio dal server, viene lanciata una funzione che ha come parametri:

    il codice del messaggio (un identificativo)
    il messaggio
    la lunghezza del messaggio
    codice:
    Private Sub AConn_DataArrival(ByVal lMsgCode As Long, ByVal sMsg As String, ByVal lMsgLength As Long)
    del messaggio io ho la struttura dati in c
    es.
    codice:
    typedef unsigned char      BYTE;        /* 1 BYTE */
    typedef unsigned short int WORD;        /* 2 BYTES */
    typedef double	           REAL;        /* 8 BYTES */
    
    typedef char TEXT8  [8+1];
    typedef char TEXT20 [20+1];
    
    typedef struct
    {
    	TEXT20		matId;
    	TEXT20		materialCode;
    	REAL		thick;
    	REAL		width;
    	TEXT8		time;
    }
    tMsgMaterial;
    come faccio, in VB6, a creare una struttura dati e poi a "spacchettarci" il messaggio?


  2. #2
    Utente di HTML.it L'avatar di EngLab
    Registrato dal
    Jan 2006
    Messaggi
    496
    Per definire un tipo di dati in VB devi fare
    codice:
    Type NomeTipo
    Attributo1 As String
    Attributo2 As Integer
    'e così via...
    End Type
    Ma spacchettare non l'ho afferrato...

  3. #3
    Converti la dichiarazione di struttura C in dichiarazione di UDT di VB6:
    codice:
    typedef unsigned char      BYTE;        /* 1 BYTE */
    typedef unsigned short int WORD;        /* 2 BYTES */
    typedef double	           REAL;        /* 8 BYTES */
    
    typedef char TEXT8  [8+1];
    typedef char TEXT20 [20+1];
    
    typedef struct
    {
    	TEXT20		matId;
    	TEXT20		materialCode;
    	REAL		thick;
    	REAL		width;
    	TEXT8		time;
    /*Consiglio: invece di usare una stringa per la data usa il vero formato di data-ora del C, che se non sbaglio è anche compatibile con quello di VB.*/
    }
    tMsgMaterial;
    codice:
    'Dichiarazione della struttura
    Type tMsgMaterial
    	matID As String * 20
    	materialCode As String * 20
    	thick As Double
    	width As Double
    	time As String * 8
    End Type
    'Dichiarazione della routine di gestione eventi:
    Private Sub AConn_DataArrival(ByVal lMsgCode As Long, ByVal sMsg As tMsgMaterial, ByVal lMsgLength As Long)
    '...
    End Sub
    Quanto poi allo spacchettamento non vedo alcun problema: accedi ai singoli membri della struttura.
    codice:
    MsgBox(sMsg.matID)
    Amaro C++, il gusto pieno dell'undefined behavior.

  4. #4
    Utente di HTML.it L'avatar di ganesha
    Registrato dal
    Jan 2003
    Messaggi
    357
    ah! ecco!
    tu dici che basta definere sMgs invece che come stringa, come tMsgMaterial...
    non so se me lo fa fare...
    ora provo

  5. #5
    Utente di HTML.it L'avatar di ganesha
    Registrato dal
    Jan 2003
    Messaggi
    357
    no..
    il parametro sMsg deve essere String...

    in c l'assegnazione di questa stringa alla struttura viene fatto in questo modo:
    codice:
    	memcpy ((void*)&msgMaterial, loc_msg, sizeof(tMsgMaterial));
    in VB6 esiste qualcosa di analogo?

  6. #6
    In linea di massima prova così:
    codice:
    'Dichiarazione della API CopyMemory
    Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    'Dichiarazione della struttura
    Type tMsgMaterial
    	matID As String * 20
    	materialCode As String * 20
    	thick As Double
    	width As Double
    	time As String * 8
    End Type
    'Dichiarazione della routine di gestione eventi:
    Private Sub AConn_DataArrival(ByVal lMsgCode As Long, ByVal sMsg As String, ByVal lMsgLength As Long)
    Dim msg As tMsgMaterial
    'Copia i dati
    CopyMemory msg, sMsg, Len(tMsgMaterial)
    'Prova ad estrarre le singole proprietà
    MsgBox(msg.matID)
    '...
    End Sub
    Importante, importantissimo: non sono sicuro che questo giochetto funzioni correttamente, perché non mi ricordo con esattezza come si comporta VB in queste situazioni; prima di eseguire il codice assicurati di avere salvato tutto, perché c'è la possibilità che il programma (e quindi l'IDE di VB, che ne interpreta il codice) vada in crash. Se stai lavorando su un PC con un sistema NT (tipo Windows 2000 o XP) non dovrebbero esserci altri effetti collaterali (al massimo un messaggio di errore di Windows, ma la cosa si dovrebbe risolvere lì).

    Per poterti dare dei consigli più sensati comunque ho bisogno di sapere esattamente che genere di oggetto è "AConn", da cui si verifica l'evento DataArrival in questione.
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Utente di HTML.it L'avatar di ganesha
    Registrato dal
    Jan 2003
    Messaggi
    357
    infatti pensavo ad una cosa del genere..

    l'ho provato: non mi dà errori, però non vengono valorizzati i campi...

    probabilmente non ho definito bene la struttura...

  8. #8
    La struttura è errata: devi togliere alla lunghezza delle stringhe un carattere (non avevo tenuto conto del terminatore NULL necessario nelle stringhe C). Temo però che il problema si verifichi per via di ciò che viene eseguito nel programma scritto in C: poiché viene copiato bit a bit il contenuto della struttura nell'array di caratteri vengono inevitabilmente copiati anche degli zeri (che saranno sicuramente presenti nella struttura); ora, il C considera che una stringa termina al primo byte uguale a 0, per cui il tuo server passerà a VB6 la stringa contenente l'UDT solo fino al primo 0 che incontra, troncandola. Puoi verificare facilmente se questa ipotesi è vera confrontando lo spazio occupato in memoria dalla struttura e la lunghezza della stringa che ti arriva nell'evento: con buone probabilità la seconda sarà di molto inferiore rispetto al primo.
    A mio parere l'unica soluzione è trasformare l'UDT in una stringa contenente i suoi campi delimitati da virgole (o punti e virgola) nel server scritto in C, passare questa stringa a VB6 e lì spacchettarla.
    codice:
    Questa struttura...
    +---------------------------------------+
    |	matId:		"10"		|
    |	materialCode:	"bgk-15"	|
    |	thick:		1.5		|
    |	width:		5.2		|
    |	time:		"11.35.45"	|
    +---------------------------------------+
    ...diventa questa stringa:
    "'10';'bgk-15';1.5;5.2;'11.35.45'"
    che viene passata in VB6 e lì viene spacchettata dentro una struttura analoga a quella di partenza.
    Due appunti:
    • nella dichiarazione della struttura C correggi il campo time da TEXT[8] a TEXT[9], perché altrimenti non viene incluso il terminatore NULL, e di conseguenza correggi la dichiarazione VB;
    • se segui la mia soluzione devi fare in modo che eventuali punti e virgola inseriti nei campi non vadano a confondersi con quelli che devono delimitare i vari campi nella stringa; trova il modo di sostituirli, magari con sequenze di escape di qualche genere.
    Amaro C++, il gusto pieno dell'undefined behavior.

  9. #9
    Utente di HTML.it L'avatar di ganesha
    Registrato dal
    Jan 2003
    Messaggi
    357
    il problema non sta solo nelle stringhe

    guarda questo codice:
    codice:
    Private Type tMsgTensionSpeed
        ActualEntrySpeed As Double 'definiti double anche in c
        SetProcessSpeed As Double
        ActualProcessSpeed As Double
        ActualExit1LineSpeed As Double
        ActualExit2LineSpeed As Double
        SetPORTension As Double
        SetCleaningTension As Double
        ActualCleaningTension As Double
        SetEntryLooperTension As Double
        ActualEntryLooperTension As Double
        SetFurnaceTension As Double
        ActualFurnaceTension As Double
        SetPicklingTension As Double
        ActualPicklingTension As Double
        SetExitLooperTension As Double
        ActualExitLooperTension As Double
        SetSkinpassEntryTension As Double
        ActualSkinpassEntryTension As Double
        SetSkinpassExitTension As Double
        ActualSkinpassExitTension As Double
        rSpare1 As Double
        rSpare2 As Double
        SetSkinpassLooperTension As Double
        ActualSkinpassLooperTension As Double
        SetTensionReelTension As Double
        ActualTensionReelTension As Double
    End Type
    
    Private Sub AC_DataArrival(ByVal lMsgCode As Long, ByVal sMsg As String, ByVal lMsgLength As Long)
        If lMsgCode = 152 Then
            Dim msg As tMsgTensionSpeed
            CopyMemory msg, sMsg, Len(lMsgLength)
            
            Text1.Text = msg.ActualEntrySpeed
            Text2.Text = msg.SetProcessSpeed
            Text3.Text = msg.ActualProcessSpeed
            Text4.Text = msg.ActualExit1LineSpeed
            Text5.Text = msg.ActualExit2LineSpeed
            Text6.Text = msg.SetPORTension
            Text7.Text = msg.SetCleaningTension
            Text8.Text = msg.ActualCleaningTension
            Text9.Text = msg.SetEntryLooperTension
            Text10.Text = msg.ActualEntryLooperTension
            Text11.Text = msg.SetFurnaceTension
            Text12.Text = lMsgCode
        End If
    End Sub
    quello che mi stampa è:
    9,42260260860008E-318 per il primo campo
    e i restanti sono tutti nulli...

  10. #10
    Utente di HTML.it L'avatar di ganesha
    Registrato dal
    Jan 2003
    Messaggi
    357
    ..invece la lunghezza della stringa sMsg è sempre 4096 anche se tMsgTensionSpeed ha lunghezza 208...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.