Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Records von Delphi in VB6 verwenden (https://www.delphipraxis.net/184059-records-von-delphi-vb6-verwenden.html)

EWeiss 22. Feb 2015 17:34


Records von Delphi in VB6 verwenden
 
Vorab es kann was länger werden.

Vergleich von Records und Types in VB
VB!
Alignment bedeutet dass die Variablen an einem Raster einer bestimmten Anzahl Bytes ausgerichtet werden.
Packed Record bedeutet dass ein Alignment von 1 verwendet wird, was soviel bedeutet wie dass kein Alignemnt verwendet werden soll.
z.B. bei einem Alignment von 4 (ist in VB üblich) werden die Variablen an einem Raster von 4 Bytes ausgerichtet.

zur Verdeutlichung ein kleines Beispiel:
Code:
Private Type TA1
    v1 As Integer ' 2 
    v2 As Integer ' 2
    v3 As Long    ' 4
End Type          

Private Type TA2
    v1 As Byte ' 1
    v2 As Long ' 4
End Type      

Private Sub Form_Load()
    Dim t1 As TA1
    MsgBox LenB(t1) '8 wie zu erwarten
   
    Dim t2 As TA1
    MsgBox LenB(t2) ' auch 8 !
   
End Sub
Habe dem Programmiere der DLL mitgeteilt das er die Records auf Packet umstellen soll.
Soweit so gut!
Nun mein Problem.
Trotz Packet kommen bei mir bei verschiedenen Records falsche werte an.

Die Functionen.
Delphi-Quellcode:
t_TagsLibrary_GetAudioAttributes   = function (Tags: HTags; AudioType: TAudioType; Attributes: Pointer): LongBool; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
Code:
Public Declare Function TagsLibrary_GetAudioAttributes Lib "TagsLib.dll" (ByVal Tags As Long, ByVal AudioType As TAudioType, ByRef Attributes As Any) As Long
Die erste Type/Record.
Delphi-Quellcode:
type
    PAudioAttributes = ^TAudioAttributes;
    TAudioAttributes = packed record
        Channels: DWord;     // number of channels (i.e. mono, stereo, etc.)
        SamplesPerSec: DWord; //sample rate
        BitsPerSample: DWord; //number of bits per sample of mono data
        PlayTime: Double;
        SampleCount: UInt64;
        BitRate: Integer;
    end;
Code:
Public Type TAudioAttributes
    Channels     As Long     ' number of channels (i.e. mono, stereo, etc.)
    SamplesPerSec As Long     ' sample rate
    BitsPerSample As Long     ' number of bits per sample of mono data
    PlayTime     As Double   ' duration in seconds
    SampleCount  As Currency ' number of total samples
    Bitrate      As Long
End Type
Die abfrage function
Code:
Public Sub GetAudioAttributes(ByVal AudioType As TAudioType)

Dim AudioAttributes As TAudioAttributes

    If AudioType = atAutomatic Then
        TagsLibrary_GetAudioAttributes LngTags, AudioType, AudioAttributes

        AttributesChannels = AudioAttributes.Channels
        AttributesSamplesPerSec = AudioAttributes.SamplesPerSec
        AttributesBitsPerSample = AudioAttributes.BitsPerSample
        AttributesPlayTime = AudioAttributes.PlayTime
        AttributesSampleCount = AudioAttributes.SampleCount
        AttributesBitrate = AudioAttributes.Bitrate
    End If

End Sub
Werte werden richtig zurückgegeben.

zweite Record
Delphi-Quellcode:
type
    PMPEGAudioAttributes = ^TMPEGAudioAttributes;
    TMPEGAudioAttributes = packed record
        Position: Int64;               //* Position of header in bytes
        Header: DWord;                 //* The Headers bytes
        FrameSize: Integer;            //* Frame's length
        Version: TMPEGVersion;         //* MPEG Version
        Layer: TMPEGLayer;             //* MPEG Layer
        CRC: LongBool;                 //* Frame has CRC
        BitRate: DWord;                //* Frame's bitrate
        SampleRate: DWord;             //* Frame's sample rate
        Padding: LongBool;             //* Frame is padded
        _Private: LongBool;            //* Frame's private bit is set
        ChannelMode: TMPEGChannelMode; //* Frame's channel mode
        ModeExtension: TMPEGModeExtension; //* Joint stereo only
        Copyrighted: LongBool;         //* Frame's Copyright bit is set
        Original: LongBool;            //* Frame's Original bit is set
        Emphasis: TMPEGEmphasis;       //* Frame's emphasis mode
        VBR: LongBool;                 //* Stream is probably VBR
        FrameCount: Int64;             //* Total number of MPEG frames (by header)
        Quality: Integer;              //* MPEG quality
        Bytes: Int64;                  //* Total bytes
    end;
Code:
Public Type TMPEGAudioAttributes
    Position     As Currency              '* Position of header in bytes
    Header       As Long                  '* The Headers bytes
    FrameSize    As Long                  '* Frame's length
    Version      As TMPEGVersion          '* MPEG Version
    Layer        As TMPEGLayer            '* MPEG Layer
    CRC          As Long                  '* Frame has CRC
    Bitrate      As Long                  '* Frame's bitrate
    SampleRate   As Long                  '* Frame's sample rate
    Padding      As Long                  '* Frame is padded
    Private_      As Long                  '* Frame's private bit is set
    ChannelMode  As TMPEGChannelMode      '* Frame's channel mode
    ModeExtension As TMPEGModeExtension    '* Joint stereo only
    Copyrighted  As Long                  '* Frame's Copyright bit is set
    Original     As Long                  '* Frame's Original bit is set
    Emphasis     As TMPEGEmphasis         '* Frame's emphasis mode
    VBR          As Long                  '* Stream is probably VBR
    FrameCount   As Currency              '* Total number of MPEG frames (by header)
    Quality      As Long                  '* MPEG quality
    Bytes        As Currency              '* Total bytes
End Type
Die abfrage function
Code:
Public Sub GetMPEGAudioAttributes(ByVal AudioType As TAudioType)

Dim MPGAudioAttributes As TMPEGAudioAttributes

    If AudioType = atMPEG Then
        TagsLibrary_GetAudioAttributes LngTags, AudioType, MPGAudioAttributes

        MPGAttributesPosition = MPGAudioAttributes.Position
        MPGAttributesHeader = MPGAudioAttributes.Header
        MPGAttributesFrameSize = MPGAudioAttributes.FrameSize
        MPGAttributesVersion = MPGAudioAttributes.Version
        MPGAttributesLayer = MPGAudioAttributes.Layer
        MPGAttributesCRC = MPGAudioAttributes.CRC
        MPGAttributesBitrate = MPGAudioAttributes.Bitrate
        MPGAttributesSampleRate = MPGAudioAttributes.SampleRate
        MPGAttributesPadding = MPGAudioAttributes.Padding
        MPGAttributesPrivate_ = MPGAudioAttributes.Private_
        MPGAttributesChannelMode = MPGAudioAttributes.ChannelMode
        MPGAttributesModeExtension = MPGAudioAttributes.ModeExtension
        MPGAttributesCopyrighted = MPGAudioAttributes.Copyrighted
        MPGAttributesOriginal = MPGAudioAttributes.Original
        MPGAttributesEmphasis = MPGAudioAttributes.Emphasis
        MPGAttributesVBR = MPGAudioAttributes.VBR
        MPGAttributesFrameCount = MPGAudioAttributes.FrameCount
        MPGAttributesQuality = MPGAudioAttributes.Quality
        MPGAttributesBytes = MPGAudioAttributes.Bytes
    End If

End Sub
Wie man sehen kann sind beide abfragen (GetMPEGAudioAttributes\GetAudioAttributes) vom Aufbau gleich.
Trotzdem sind die Rückgabewerte von GetMPEGAudioAttributes falsch.

Kann mir nun jemand sagen woran das liegen könnte..
Warum sind die Abfragen beim ersten Record richtig und beim zweiten wiederum nicht!
Meine Vermutung ist das die Typen Int64 mit VB6 nicht kompatibel sind obwohl Currency und Int64 jeweils 8 Byte groß sind.

Hoffe das sich jemand die mühe macht das durchzulesen.

gruss

Sir Rufo 22. Feb 2015 17:40

AW: Records von Delphi in VB verwenden
 
Kleiner Tippfehler im Beitrag: Es sind 8 Byte und nicht 8 Bit

Gibt es einen Grund, warum dort mal
Delphi-Quellcode:
UInt64
und mal
Delphi-Quellcode:
Int64
zu
Delphi-Quellcode:
Currency
gemappt wird?

Gibt es unter VB keinen
Delphi-Quellcode:
Int64
-Typen?
Doch, gibt es: https://msdn.microsoft.com/en-us/library/47zceaw7.aspx

EDIT Ok, VB6 kennt es nicht https://msdn.microsoft.com/en-us/lib...=vs.60%29.aspx

Hier mal im Vergleich die Delphi-Typen
http://docwiki.embarcadero.com/RADSt...e_Datenformate

EWeiss 22. Feb 2015 18:02

AW: Records von Delphi in VB verwenden
 
Zitat:

Kleiner Tippfehler im Beitrag: Es sind 8 Byte und nicht 8 Bit
Danke werde es berichtigen ;)

Zitat:

Gibt es einen Grund, warum dort mal UInt64 und mal Int64 zu Currency gemappt wird?
Ja weil VB6 nur Currency als alternative kennt also 8 Byte
Zudem muss ich die gleiche Anzahl an Bytes verwenden damit der Recordsize gleich bleibt.
Mein Unverständnis. Frage mich warum überhaupt bei 32 Bit Anwendungen UInt64/Int64 verwendet werden.
Macht das sinn?
Warum UInt64 und mal Int64 entzieht sich meiner Kenntnis müsste ich den Developer der DLL mal fragen.

Zitat:

Gibt es unter VB keinen Int64 -Typen?
Doch, gibt es: https://msdn.microsoft.com/en-us/library/47zceaw7.aspx
Leider nein.
Nicht verwechseln VB6 nicht VB.NET
Hab den Thread Titel geändert ;)

Zitat:

Hier mal im Vergleich die Delphi-Typen
http://docwiki.embarcadero.com/RADSt...e_Datenformate
Danke! :)
Interessant und immer gut wenn man so eine Tabelle hat.

ConnorMcLeod 22. Feb 2015 18:38

AW: Records von Delphi in VB6 verwenden
 
Quatsch, nicht alles gelesen gehabt ...

EWeiss 22. Feb 2015 18:44

AW: Records von Delphi in VB6 verwenden
 
Zitat:

Zitat von ConnorMcLeod (Beitrag 1291006)
Das erste Mal mappste Currency auf UInt64 und das zweite Mal auf Int64. Vllt isses das?

Wo?
Es sind doch unterschiedliche Records.
Und komplett von einander getrennt.

Und werden separat aufgerufen
Code:
TagsLibrary_GetAudioAttributes LngTags, AudioType, AudioAttributes
TagsLibrary_GetAudioAttributes LngTags, AudioType, MPGAudioAttributes
gruss

ConnorMcLeod 22. Feb 2015 18:51

AW: Records von Delphi in VB6 verwenden
 
Da: (aber ich glaube, das hattet Ihr schon besprochen, oder?)
Zitat:

Zitat von EWeiss (Beitrag 1290999)

Die erste Type/Record.
Delphi-Quellcode:
type
    TAudioAttributes = packed record
        SampleCount: UInt64;
    end;
Code:
Public Type TAudioAttributes
    SampleCount  As Currency ' number of total samples
End Type
zweite Record
Delphi-Quellcode:
type
    TMPEGAudioAttributes = packed record
        Position: Int64;               //* Position of header in bytes
        FrameCount: Int64;             //* Total number of MPEG frames (by header)
        Bytes: Int64;                  //* Total bytes
    end;
Code:
Public Type TMPEGAudioAttributes
    Position     As Currency              '* Position of header in bytes
    FrameCount   As Currency              '* Total number of MPEG frames (by header)
    Bytes        As Currency              '* Total bytes
End Type


Sir Rufo 22. Feb 2015 19:03

AW: Records von Delphi in VB6 verwenden
 
Wenn ich mir
Delphi-Quellcode:
Int64
und
Delphi-Quellcode:
UInt64
ansehe, hätte ich schon fast gedacht, da müsste
Delphi-Quellcode:
Int64
besser passen (Vorzeichen-Bit, aber ...

...
Delphi-Quellcode:
Currency
wird als Container für 8 Bytes ge(miss)braucht, von daher würde ich da auf jeden Fall mal
Delphi-Quellcode:
Int64
gegen
Delphi-Quellcode:
UInt64
bzw.
Delphi-Quellcode:
Cardinal
(das Gleiche in grün) tauschen.

Delphi-Quellcode:
type
    PMPEGAudioAttributes = ^TMPEGAudioAttributes;
    TMPEGAudioAttributes = packed record
        Position: UInt64; //* Position of header in bytes
        Header: DWord; //* The Headers bytes
        FrameSize: Integer; //* Frame's length
        Version: TMPEGVersion; //* MPEG Version
        Layer: TMPEGLayer; //* MPEG Layer
        CRC: LongBool; //* Frame has CRC
        BitRate: DWord; //* Frame's bitrate
        SampleRate: DWord; //* Frame's sample rate
        Padding: LongBool; //* Frame is padded
        _Private: LongBool; //* Frame's private bit is set
        ChannelMode: TMPEGChannelMode; //* Frame's channel mode
        ModeExtension: TMPEGModeExtension; //* Joint stereo only
        Copyrighted: LongBool; //* Frame's Copyright bit is set
        Original: LongBool; //* Frame's Original bit is set
        Emphasis: TMPEGEmphasis; //* Frame's emphasis mode
        VBR: LongBool; //* Stream is probably VBR
        FrameCount: UInt64; //* Total number of MPEG frames (by header)
        Quality: Integer; //* MPEG quality
        Bytes: UInt64; //* Total bytes
    end;
Edit

Ok, hört sich auch irgendwie nach Voodoo an (wenn ich so länger drüber sinniere).

Wie sind denn diese
Delphi-Quellcode:
TMPEG...
Typen definiert? Enums, Records, ...?
Bei Enums muss man aufpassen, denn die können unterschiedliche Byte-Längen haben (wenn man da nicht einwirkt).

EWeiss 22. Feb 2015 19:07

AW: Records von Delphi in VB6 verwenden
 
Zitat:

Da: (aber ich glaube, das hattet Ihr schon besprochen, oder?)
Ja ;)
Aber wie gesagt Currency ist ja nur der vergleich Daten Type für UInt64 und Int64
Um den Record in der Größe gleichzuhalten muss ich einen Daten Type von 8 Bytes verwenden.

Auch wenn er signiert bzw. unsigniert nicht gleich ist mit den in Delphi deklarierten Typ
Currency = 6,312
Int64 = 63120

Das sind dann halt die Unterschiede.

Wie schon gesagt die Records sind voneinander getrennt warum er jetzt einmal UInt64 und Int64 verwendet?
Kein Ahnung..

gruss

EWeiss 22. Feb 2015 19:10

AW: Records von Delphi in VB6 verwenden
 
Zitat:

von daher würde ich da auf jeden Fall mal Int64 gegen UInt64 bzw. Cardinal (das Gleiche in grün) tauschen.
Danke werde ihm das mal vorschlagen da ich keinen zugriff auf dem Quelltext habe.

gruss

Sir Rufo 22. Feb 2015 19:17

AW: Records von Delphi in VB6 verwenden
 
Zitat:

Zitat von EWeiss (Beitrag 1291012)
Zitat:

von daher würde ich da auf jeden Fall mal Int64 gegen UInt64 bzw. Cardinal (das Gleiche in grün) tauschen.
Danke werde ihm das mal vorschlagen da ich keinen zugriff auf dem Quelltext habe.

gruss

Nee, das wird es wohl nicht sein, ich tippe eher mal auf die
Delphi-Quellcode:
TMPEG...
Typen. Was ist das, bzw. wie sind die deklariert? (s. Edit meiner Antwort)

EWeiss 22. Feb 2015 19:19

AW: Records von Delphi in VB6 verwenden
 
Zitat:

Wie sind denn diese TMPEG... Typen definiert? Enums, Records, ...?
Bei Enums muss man aufpassen, denn die können unterschiedliche Byte-Längen haben (wenn man da nicht einwirkt).
Ich weis jetzt nicht welche du speziell meinst aber mal das hier.

Delphi-Quellcode:
t_TagsLibrary_GetAudioAttributes   = function (Tags: HTags; AudioType: TAudioType; Attributes: Pointer): LongBool; {$IFDEF MSWINDOWS}stdcall{$ELSE}cdecl{$ENDIF};
Delphi-Quellcode:
type
    TAudioType = (atAutomatic, atFlac, atMPEG, atDSDDSF, atWAV, atAIFF, atMP4, atOpus, atVorbis, atWMA, atWAVPack, atMusePack);
Das TMPEGAudioAttributes hatten wir ja schon.

Delphi-Quellcode:
type
    TMPEGVersion = (tmpegvUnknown, tmpegv1, tmpegv2, tmpegv25);

    TMPEGLayer = (tmpeglUnknown, tmpegl1, tmpegl2, tmpegl3);

    TMPEGChannelMode = (tmpegcmUnknown, tmpegcmMono, tmpegcmDualChannel, tmpegcmJointStereo, tmpegcmStereo);

    TMPEGModeExtension = (tmpegmeUnknown, tmpegmeNone, tmpegmeIntensity, tmpegmeMS, tmpegmeIntensityMS);

    TMPEGEmphasis = (tmpegeUnknown, tmpegeNo, tmpege5015, tmpegeCCITJ17);
gruss

Sir Rufo 22. Feb 2015 19:22

AW: Records von Delphi in VB6 verwenden
 
Ich wette in VB hat ein Enum immer 4 Byte, in Delphi 1, 2 oder 4 Bytes

Hier mal der Link zur Doku.
http://docwiki.embarcadero.com/RADSt...n_%28Delphi%29

Ok, da es alles Enums sind, sage ich, das liegt zu 99,9999% an der Enum Größe

EWeiss 22. Feb 2015 19:26

AW: Records von Delphi in VB6 verwenden
 
Zitat:

Zitat von Sir Rufo (Beitrag 1291016)
Ich wette in VB hat ein Enum immer 4 Byte, in Delphi 1, 2 oder 4 Bytes
Ok, da es alles Enums sind, sage ich, das liegt zu 99,9999% an der Enum Größe

Die frage wäre dann wie ändern in Delphi?
Wüsste jetzt auf anhieb nicht wie ich das in VB casten soll.

Das würde auch erklären warum der zweite Record ungepackt genau so groß wie in VB ist. (88 Bytes)
Während der erste nur mit Packed Record funktioniert. Siehe Anlage.

Hmm.. jetzt wird es schwierig.

gruss

jfheins 22. Feb 2015 19:33

AW: Records von Delphi in VB6 verwenden
 
Zitat:

Zitat von EWeiss (Beitrag 1291017)
Die frage wäre dann wie ändern in Delphi?
Wüsste jetzt auf anhieb nicht wie ich das in VB casten soll.

Wenn du in Delphi noch einen "Fake"-Wert zum enum hinzufügst, und diesem dan Wert $3000000 oder so gibst, dann sollte Delphi für den enum auch vier Byte benötigen.

EWeiss 22. Feb 2015 19:36

AW: Records von Delphi in VB6 verwenden
 
Zitat:

Zitat von jfheins (Beitrag 1291018)
Zitat:

Zitat von EWeiss (Beitrag 1291017)
Die frage wäre dann wie ändern in Delphi?
Wüsste jetzt auf anhieb nicht wie ich das in VB casten soll.

Wenn du in Delphi noch einen "Fake"-Wert zum enum hinzufügst, und diesem dan Wert $3000000 oder so gibst, dann sollte Delphi für den enum auch vier Byte benötigen.

Bitte kannst du das genauer erklären ?
Kleines Beispiel..?
Damit ich dem Developer mitteilen kann wie er das machen soll.

Aber Achtung die DLL unterstützt auch anderer Developer-Sprachen es muss auf jeden fall kompatibel bleiben.

gruss

Namenloser 22. Feb 2015 19:40

AW: Records von Delphi in VB6 verwenden
 
Ich denke, er meint so:
Delphi-Quellcode:
type
    TMPEGVersion = (tmpegvUnknown, tmpegv1, tmpegv2, tmpegv25, tmpegdummy = $FFFFFFFF);
Dann muss Delphi den Typ auf 4 Bytes erweitern.

EWeiss 22. Feb 2015 19:43

AW: Records von Delphi in VB6 verwenden
 
Zitat:

Zitat von Namenloser (Beitrag 1291020)
Ich denke, er meint so:
Delphi-Quellcode:
type
    TMPEGVersion = (tmpegvUnknown, tmpegv1, tmpegv2, tmpegv25, tmpegdummy = $FFFFFFFF);
Dann muss Delphi den Typ auf 4 Bytes erweitern.

Ahh ok Danke..
Wo bekomme ich jetzt die Infos her das ein VB6 Enum auch wirklich 4 Byte hat?
Nicht das ich es euch nicht glaube, will mich aber trotzdem mal informieren (ge-googled hab ich schon)

gruss

Sir Rufo 22. Feb 2015 20:39

AW: Records von Delphi in VB6 verwenden
 
Und was ist mit
Delphi-Quellcode:
{$Z4}
oder
Delphi-Quellcode:
{$MINENUMSIZE 4}
wie der von mir gepostete Link zur Dokumentation zeigt? :roll:

EWeiss 22. Feb 2015 20:46

AW: Records von Delphi in VB6 verwenden
 
Zitat:

Zitat von Sir Rufo (Beitrag 1291028)
Und was ist mit
Delphi-Quellcode:
{$Z4}
oder
Delphi-Quellcode:
{$MINENUMSIZE 4}
wie der von mir gepostete Link zur Dokumentation zeigt? :roll:

verstehe ich irgendwie nicht.
Kannst mir bitte erklären?

Meinst den Schalter {$MINENUMSIZE 4} für Enums setzen?

gruss

Sir Rufo 22. Feb 2015 20:52

AW: Records von Delphi in VB6 verwenden
 
Muss ich jetzt schon die Dokumentation vorlesen?

Muss wohl so sein ... Auszug aus der Delphi-Dokumentation (Link habe ich schon ein paar Beiträge vorher angegeben):
Zitat:

Die Direktive $Z legt die minimale Speichergröße für Aufzählungstypen in Delphi fest.
Ein Aufzählungstyp wird als vorzeichenloses Byte gespeichert, wenn die Aufzählung aus maximal 256 Werten besteht und der Typ im Status {$Z1} (Voreinstellung) deklariert wurde. Enthält der Aufzählungstyp mehr als 256 Werte oder wurde er im Status {$Z2} deklariert, wird er als vorzeichenloses Wort gespeichert. Aufzählungstypen, die im Status {$Z4} deklariert wurden, werden als vorzeichenloses Doppelwort gespeichert.
{$Z2} und {$Z4} sind hilfreich, wenn eine Schnittstelle zu C und C++ Bibliotheken benötigt wird, die Aufzählungstypen in der Regel als Wörter oder Doppelwörter darstellen.
Zur Erläuterung:

Wort und Doppelwort sind durch die (wohl automatische) Übersetzung gelaufen und lauteten im Original Word (2 Byte) und Doubleword (4 Byte).

Der letzte Satz aus dem Zitat ist so lange zu lesen, bis man ihn verstanden hat ... (VB ist kein C/C++ aber da von MS in den Dingen wohl ähnlich bis gleich)

EWeiss 22. Feb 2015 20:57

AW: Records von Delphi in VB6 verwenden
 
Zitat:

Muss ich jetzt schon die Dokumentation vorlesen?
jo sorry!
Hatte meinen Beitrag editiert.
Zitat:

Meinst den Schalter(Direktive) {$MINENUMSIZE 4} für Enums setzen?
gruss

EWeiss 23. Feb 2015 00:27

AW: Records von Delphi in VB6 verwenden
 
Ok nach der Änderung auf 4 Bytes für enum in der Delphi DLL funktioniert es jetzt..

Danke allen die geholfen haben.

gruss


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:33 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz