VB: Long in Byte-Array einlesen...

  • #1
F

Fizbin

Bekanntes Mitglied
Themenersteller
Dabei seit
09.07.2003
Beiträge
220
Reaktionspunkte
0
Hallo.

Mal ne dumme Frage: Wie stell ich das an das ich einen Long- Wert in ein Byte-Array bekomme?


Bsp.:
Ausgang:

Long = &H FF FC 03 3F

(ungefähres) Ziel:

Byte(0)= &H FF
Byte(1)= &H FC
Byte(2)= &H 03
Byte(3)= &H 3F


Gruß Fizbin
 
  • #2
Hi

Das geht so:
Code:
Private Sub Command1_Click()
    Dim sHexadezimal As String
    Dim bZeichen(3) As Byte
    Dim i As Byte
    
    Const nHexadezimal As Long = &HFFFC033F
    sHexadezimal = Hex(nHexadezimal)
    
    For i = 0 To 3
        bZeichen(i) = CByte(CLng(&H & Mid$(sHexadezimal, i * 2 + 1, 2)))
        
       ->MsgBox Format$(Hex(bZeichen(i)), 00)
    Next i
End Sub

Mfg Alexander
 
  • #3
Danke schon mal für die Antwort. Das muss aber auch irgendwie auch ohne den Umweg über die Stringbearbeitung gehen. Ich hab vor Jahren mal sowas mit C++ mal gemacht. In VB müsste das doch auch gehen.

Edit: Problem bei der obigen Lösung wäre auch das der Wert keine Konstante ist, d.h. der Wert (long) kann auch 0 sein. Ergebnis wäre ein leerer String und vermutlich ein Feheler bei MID
 
  • #4
Dann fang das doch einfach mit einem if the else ab ;)
Anstatt mit Konstanten kannste den Hex Wert ja auch direkt angeben. Den Wert übergibst Du dann als Parameter.
Meine VB Zeiten sind schon etwas her, aber IMHO kann der Rückgabewert einer Funktion auch ein Array sein, so dass Du die Sub auch als Function deklarieren kannst.

Eddie
 
  • #5
Hallo

Die Lösung ist ein wenig durch die Brust ins Auge. Ich verwandle eine vier-Byte-Long Zahl in einen String- Datentyp, um dann die Stringteile in Byte-Datentypen umzuwandeln? Dann noch einen Fehlerabfang in dem die Stringteile, mittels Format Anweisungen oder wie auch immer, bearbeitet werden?

Es muss auch direkter gehen. Ich denke da an sowas wie Pointer die auf den Adressbereich der Long-Zahl zeigen (auch wenn VB keine richtigen Zeiger unterstütz).

Wie kriege ich es sonst hin, ohne Umweg über die Stringbearbeitung, das ich die einzelnen Bytes einer 4-Byte LONG Zahl auslesen kann. Gerne auch Bitweise.

Gruß Fizbin
 
  • #6
Hi

In C würde es dazu den Union type geben, da benutzen die definierten Typen innerhalb der Struktur den selben Speicher.

Ansonsten müsste auch ein shiften nach rechts helfen.
Du weißt dem ersten Byte den long zu, dann sollte er nur die letzten 8 nehmen. Dann shiftest du den long um 8 nach rechts und wieder das gleiche.

Gruß, Michael
 
  • #7
Hallo.

Danke für die Antwort. Hab mich mitlerweile entschieden Codeteile in C/C++ geschriebene DLLs auszugliedern.
Einige Sachen scheint VB wirklich nicht zu können. Ein anderer Grund ist die Performance- der angesprochende Vorgang soll ca. 100 mal pro Sek. durchgeführt werden (es soll übrigens eine an den USB-Port angeschlossene Schaltung im Hintergrund abgefragt werden).

Leider ist es schon ein bisschen her mit meiner C/C++ Programmierung. Hab aber mittlerweile testweise eine DLL erstellen können, die aus dem VB-Code herraus aufgerufen werden kann, mit einem übergebenen Parameter (byVal) eine kleine Berechnung durchführt und das Ergebnis an den VB-Code zurückgibt.
Nun werde ich mal testen ob ich das Bytearray irgendwie ByRef übergeben kann und wie ich dann das Long in den Array bekomme. In sofern denke ich das mir der Tip mit Union type im übernächsten Schritt bestimmt hilft. ;)


Du weißt dem ersten Byte den long zu
Ach ja... das zuweisen... ;D ;)
Wie geht das denn in VB?
byte(i)= long //Überlauf wenn Long > 255
byte(i)= &long //Zeiger auf Variablen gibts in VB nicht.

Das Shiften von Bits geht in VB leider auch nicht so einfach wie in C/C++ (an dieser Stelle ist C wirklich mal komfortabeler als VB ;))

Ich denke das mit der DLL ist eine gute Lösung. Bei Fragen zu dem C- Code werde ich mich nochmal in diesem Thread melden, bzw. die Lösung posten.

Gruß Fizbin
 
  • #8
So.
Nun hab ich ein wenig rumprobiert und eine funktionsfähige Lösung gefunden. Wenn jemand Verbesserungsvorschläge hat, her damit ;)

die umrechnen.dll besteht aus 2 Dateien.
---1. umrechnen.def---
Code:
LIBARY umrechnen
EXPORTS
byte_to_array

----2. umrechnen.c
Code:
union ByteArry{
unsigned char ch0[4];
long wert;
} var1;



long _declspec( dllexport ) _stdcall byte_to_array (long lWert, char  *buffer0,  char  *buffer1, char  *buffer2 , char  *buffer3)
{

//initialisieren
var1.ch0[0]=0;
var1.ch0[1]=0;
var1.ch0[2]=0;
var1.ch0[3]=0;
var1.wert =0;

//Long Parameter union zuweisen
var1.wert = lWert;

// 
var1.ch0[0] = var1.wert;


//Übergebene Pointer auf union chars setzten
*buffer0 =var1.ch0[0]; 
*buffer1 =var1.ch0[1];
*buffer2 =var1.ch0[2];
*buffer3 =var1.ch0[3];
return 5;
}

Soweit der c-/dll- Teil. Aus dem VB- Code ist die Funktion nun unter dem Namen byte_to_array erreichbar. Als Parameter werden der long-Wert (byRef) und die 4 Bytes (ByRef) übergeben.


Code:
Private Declare Function byte_to_array& Lib umrechnen.dll (ByVal Wert As Long, ByRef Ergebnis0 As Byte, ByRef Ergebnis1 As Byte, ByRef Ergebnis2 As Byte, ByRef Ergebnis3 As Byte)

Private Sub Command1_Click()
    Dim l As Long
    Dim Wert(3) As Byte
    Dim res As Long
    
    l = &HFCFDFEF0
     debug.Print Ausgang:   & Hex(l)
    res = byte_to_array(l, Wert(0), Wert(1), Wert(2), Wert(3))
    
    For i = 0 To 3
        Debug.Print Byte  &  i, Hex(Wert(i))
    Next i

End Sub


Ausgabe im VB-Debugfenster:
Ausgang: FCFDFEF0
Byte 0 F0
Byte 1 FE
Byte 2 FD
Byte 3 FC
(An dieser Stelle ist mir gleich ob sich das niedrigste oder höchste Byte der Long-Zahl in Byte 0 befindet).



Hat jemand noch Verbesserungsvorschläge zum C-Teil. Ist wie erwähnt schon länger her bei mir mit C. Mir wird (komischerweise nur manchmal) beim Erstellen der Dll auch von VC++ die Warnung G:\temp\umrechnen\umrechnen.c(22) : warning C4244:->=' : Konvertierung von->long-> in->unsigned char->, moeglicher Datenverlust ausgegeben.
Desweitern habe ich Probleme mit VC++, immer wenn ich die .dll erstellen oder debugen möchte und ein Fehler im Code ist (z.B. ein fehlendes Semikolon), lässt sich das erstellen nicht mehr anhalten (F7). Es hilft nur das abschiessen über den Taskmanager.

Gruß Fizbin
 
  • #9
Hi

Probier mal aus ob das reicht:
Code:
void _declspec( dllexport ) _stdcall byte_to_array (long lWert, char  *buffer0,  char  *buffer1, char  *buffer2 , char  *buffer3)
{


//Long Parameter union zuweisen
var1.wert = lWert;


//Übergebene Pointer auf union chars setzten
*buffer0 =var1.ch0[0];
*buffer1 =var1.ch0[1];
*buffer2 =var1.ch0[2];
*buffer3 =var1.ch0[3];
}

Gruß, Michael
 
  • #10
Hallo.

Stimmt. Es klappt auch ohne die Zeile
var1.ch0[0] = var1.wert;
Nun habe die Sache mit dem union type auch erst richtig begriffen ;). Danke soweit.

(und natürlich reicht auch ein VOID als Rückgabe der Funktion).


Es ist an der Zeit meine C-Bücher mal wieder vorzukramen. Und noch viel wichtiger: VC++ wieder soweit zu kriegen das ich das Erstellen anhalten, bzw Debuggen kann. (Wenn ich ein Haltepunkt setzte und debuggen möchte, hält der Code zwar am Haltepunkt aber es geht nicht mehr weiter. Mal schauen ob die Neuinstall. von VC++ was bringt.

Gruß Fizbin
 
  • #11
Hi

Hab tatsächlich doch noch ein VB Code gefunden um zumindest ein long in 2 Ints zu lesen (daran anlehnent geht es natürlich auch mit 4 Bytes). Natürlich ist die C-Dll in dem Fall die deutlich bessere Alternative, der Vollständigkeit halber wollte ich den VB- Code aber auch noch posten.

Code:
'long in zwei ints
Public Function HiWord%(ByVal x&)
    HiWord = (x And &HFFFF0000) / &H10000
End Function

Public Function LoWord%(ByVal x&)
    x& = x& And &HFFFF&
    If x > 32767 Then
        LoWord = x - 65536
    Else
        LoWord = x
    End If
End Function


Private Sub Command1_Click()
Dim wert As Long
wert = &HDFFF100E
hi = HiWord(wert)
lo = LoWord(wert)
Debug.Print Hex(hi), Hex(lo)
End Sub
(Aus dem Buch Visual Basic 6 von Michael Kofler;isbn 3-8-273-1428-3 <--Empfehlung)

Gruß Fizbin
 
  • #12
Ich würde die API-Funktion CopyMemory verwenden:

Code:
Private Declare Sub CopyMemory Lib kernel32 Alias RtlMoveMemory (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Public Function LongToByteArray(ByVal L As Long) As Byte()
Dim Buffer(3) As Byte
    CopyMemory Buffer(0), L, 4
    LongToByteArray = Buffer
End Function
 
  • #13
Danke Phillip.

Genau das war es was ich ursprünglich gesucht und nicht gefunden hatte. :D.

Da meine DLL nun auch Funktionen für das shiften, setzten und checken von Bits enthält (was unter VB ebenfalls schwer zu realisieren ist), werde ich diese weiterhin einsetzten.
 
Thema:

VB: Long in Byte-Array einlesen...

ANGEBOTE & SPONSOREN

Statistik des Forums

Themen
113.840
Beiträge
707.963
Mitglieder
51.494
Neuestes Mitglied
Flensburg45
Oben