IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Besoin d'explication sur le fonctionnement de Stream.Position


Sujet :

Langage Delphi

  1. #1
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 851
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 851
    Points : 15 265
    Points
    15 265
    Par défaut Besoin d'explication sur le fonctionnement de Stream.Position
    Bonjour,

    Je voulais porter un petit projet (pas de moi) développé en Delphi (version inconnue, pas récente) et qui fonctionne bien dans ma VM 2000, vers mon Lazarus qui tourne sous Linux Debian, tout ce petit monde en 32 bits.

    Et une fonction ne fait pas ce que j'attends d'elle.
    À grands coups de ShowMessage j'ai trouvé que ça se passait là :
    Code Delphi : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ShowMessage(IntToStr(Stream.Position));  // = 20, suite aux opérations précédentes, idem Delphi-Lazarus
    Stream.Position := Stream.Position + ReadWord(Stream) * 12; 
    ShowMessage(IntToStr(Stream.Position));  // = 130 en Delphi et 128 en Lazarus !

    Comment expliquer ce 130 en Delphi ?
    130 = 110 - 20, et 110 n'est pas divisible par 12, que je sache.
    128 = 108 - 20, et 108 div 12 = 9 ; dans Lazarus, ça semble déjà plus net.

    La fonction ReadWord :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function ReadWord(Stream: TStream): Word; 
    begin 
      Stream.ReadBuffer(Result, SizeOf(Result)); 
    end;
    Mais pourquoi Delphi fait-il +2 en fin de calcul ?

    Voilà, si quelqu'un pouvait m'expliquer ce petit mystère, je lui en serai éternellement reconnaissant (si si )

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 871
    Points : 11 361
    Points
    11 361
    Billets dans le blog
    6
    Par défaut
    Voici qui est amusant !
    On dirait que Lazarus lit Stream.position puis lit le nombre d'entrées de l'IFD pour ajouter leur taille, alors que Delphi ferait dans l'autre sens, en lisant donc Stream.position après qu'il a avancé de 2, d'où la différence !

  3. #3
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 851
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 851
    Points : 15 265
    Points
    15 265
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Voici qui est amusant !
    Coucou, Yves,

    t'as raison, c'est amusant
    Si j'avais pas eu ma VM 2k avec mon vieux D7 que j'ai truffé de ShowMessage, je sais pas comment j'aurais fait...

    Citation Envoyé par tourlourou Voir le message
    On dirait que Lazarus lit Stream.position puis lit le nombre d'entrées de l'IFD pour ajouter leur taille
    Et comment tu sais qu'il y a de l'IFD dans l'air ? Je ne l'ai pas mentionné

    T'as déjà vu passer ce projet ? (Oui, vous m'avez titillé les neurones avec cette histoire de date Exif, de l'autre côté de la rue )

  4. #4
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 871
    Points : 11 361
    Points
    11 361
    Billets dans le blog
    6
    Par défaut
    Bonsoir Jean-Pierre
    Ceci demandait à être vérifié quand même, ce n'était qu'une hypothèse. Plus une pour le sujet !

    Ça me titille aussi, et j'adapte lentement mon code sous Lazarus, dans un objet pour en faciliter l'utilisation.

  5. #5
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 561
    Points : 3 951
    Points
    3 951
    Par défaut
    Salut

    Ta fonction ReadWord a quand même un gros effet de bord : la méthode ReadBuffer ne provoque-t-elle, par hasard, la lecture de 2 octets (Word) et donc la mise à jour de la propriété Position ?

    Tu lis (Word)9, tu progresses de 2 (ReadBuffer), puis tu multiplies 9 * 12 = 108 que tu ajoutes à la position que tu viens d'altérer par la lecture de la valeur 9 d'où 20 + 2 + 9*12 = 130.

    Perso, je dirai que c'est le p'tit père Delphi qui a raison sur ce coup-là. C'est pas rassurant sur les portages de Delphi à Lazarus.
    Il serait intéressant de comparer les versions de la méthode ReadBuffer entre Delphi et Lazarus.

    J'accepte les cartes Visa

    @+

  6. #6
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 851
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 851
    Points : 15 265
    Points
    15 265
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    On dirait que Lazarus lit Stream.position puis lit le nombre d'entrées de l'IFD pour ajouter leur taille, alors que Delphi ferait dans l'autre sens, en lisant donc Stream.position après qu'il a avancé de 2, d'où la différence !
    Ça promet du sport quand je vais devoir m'amuser à aller farfouiller dans les sous-tags propriétaires du Maker : sur mon Canon les vignettes font 160 x 106, telles que définies dans le tag Thumbnail Image Valid Area.

    Dans le prog que j'étudie, elles s'affichent en 160 x 120, classique, donc bandes noires en haut et en bas, très moche

    Bah, ça va m'occuper.

  7. #7
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 871
    Points : 11 361
    Points
    11 361
    Billets dans le blog
    6
    Par défaut
    Ce qui est super, c'est qu'il y a une norme, mais qu'elle n'est pas respectée ! Ou alors qu'il y a tellement d'exceptions... Ou que ce qui n'est pas expressément interdit, tout en ne semblant pas réellement permis, se retrouve quand même dans certains fichiers !

  8. #8
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 851
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 851
    Points : 15 265
    Points
    15 265
    Par défaut
    Yep !
    Citation Envoyé par e-ric Voir le message
    Ta fonction ReadWord a quand même un gros effet de bord : la méthode ReadBuffer ne provoque-t-elle, par hasard, la lecture de 2 octets (Word) et donc la mise à jour de la propriété Position ?

    Tu lis (Word)9, tu progresses de 2 (ReadBuffer), puis tu multiplies 9 * 12 = 108 que tu ajoutes à la position que tu viens d'altérer par la lecture de la valeur 9 d'où 20 + 2 + 9*12 = 130.

    Perso, je dirai que c'est le p'tit père Delphi qui a raison sur ce coup-là.
    Ouais ouais ouais ouais-ouais, dit comme ça c'est très clair et ça semble logique.

    Citation Envoyé par e-ric Voir le message
    C'est pas rassurant sur les portages de Delphi à Lazarus.
    Il serait intéressant de comparer les versions de la méthode ReadBuffer entre Delphi et Lazarus.
    Voilà ce que je peux proposer pour Lazarus (pour Delphi je passe, j'ai un D7 perso), je la fais courte :
    dans un fichier nommé classesh.inc (probablement suivant le principe de classes.pas) on trouve
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    { TStream abstract class }
     
      TStream = class(TObject)
      private
      protected
        procedure ReadNotImplemented;
      public
        function Read(var Buffer; Count: Longint): Longint; virtual;
        procedure ReadBuffer(var Buffer; Count: Longint);
        property Position: Int64 read GetPosition write SetPosition;
      end;
    ReadBuffer pointe dans un fichier streams.inc sur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TStream.ReadBuffer(var Buffer; Count: Longint);
    begin
       if Read(Buffer,Count)<Count then
         Raise EReadError.Create(SReadError);
    end;
    Le Read ci-dessus correspond à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function TStream.Read(var Buffer; Count: Longint): Longint;
    begin
      ReadNotImplemented;
      Result := 0;
    end;
    Ça commence à devenir rigolo, surtout en lisant ReadNotImplemented :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure TStream.ReadNotImplemented;
    begin
      raise EStreamError.CreateFmt(SStreamNoReading, [ClassName]) at get_caller_addr(get_frame);
    end;
    Comment fait-on pour lire un buffer ? Mystère !, d'autant plus que je n'ai pas vu le message d'erreur annoncé
    Mais le plus marrant dans tout ça, c'est qu'en pas-à-pas, en mettant la souris sur Stream.Position, une infobulle m'annonce que l'objet Stream n'a pas de property Position ! Et pourtant elle est visible dans l'extrait que je cite.
    Quand tu vois ça sur ton écran, tu te demandes ce que t'as fumé ou qu'est-ce qu'on a mis dans ta bouffe !

    Ce qui est plus ennuyeux (pour comprendre), c'est qu'il n'y a pas moyen de plonger dans ReadBuffer ou Read en pas-à-pas approfondi, probablement lié au fait qu'il s'agit de fichiers .inc. Dommage...

    Citation Envoyé par tourlourou Voir le message
    Ce qui est super, c'est qu'il y a une norme, mais qu'elle n'est pas respectée ! Ou alors qu'il y a tellement d'exceptions... Ou que ce qui n'est pas expressément interdit, tout en ne semblant pas réellement permis, se retrouve quand même dans certains fichiers !
    Mouais, un peu ce que je disais là-bas...
    Et pourtant certains logiciels de développement Raw sous Linux arrivent à remonter tout et le reste !
    Ils ont dû en ch..., les pôvres

  9. #9
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 448
    Points
    28 448
    Par défaut
    la différence n'est pas dans la fonction (THandleStream.) ReadBuffer mais dans l'ordre dévaluation de l'addition :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     Stream.Position + ReadWord(Stream) * 12;
    // ou
     ReadWord(Stream) * 12 + Stream.Position;
    // il faudrait tester ceci
      Stream.Seek(12 * ReadWord(Stream), soCurrent);

  10. #10
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 561
    Points : 3 951
    Points
    3 951
    Par défaut
    @Jipété
    La classe TStream est abstraite, c'est dans les classes dérivées comme TFileStream qu'il faut chercher l'implémentation réelle.

    @Pascal
    Je n'y avais pas pensé; c'est une piste à explorer. Mais cela me semble fort en chocolat quand même.

    @+

  11. #11
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 851
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 851
    Points : 15 265
    Points
    15 265
    Par défaut
    Bonjour à tous
    Citation Envoyé par Paul TOTH Voir le message
    la différence n'est pas dans la fonction (THandleStream.) ReadBuffer mais dans l'ordre d'évaluation de l'addition :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     Stream.Position + ReadWord(Stream) * 12;
    // ou
     ReadWord(Stream) * 12 + Stream.Position;
    // il faudrait tester ceci
      Stream.Seek(12 * ReadWord(Stream), soCurrent);
    Trop fort le Paul
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Stream.Position + ReadWord(Stream) * 12;  // original, donne 128 :-(
    ReadWord(Stream) * 12 + Stream.Position;  // donne 130 :-)
    Stream.Seek(12 * ReadWord(Stream), soCurrent);  // donne 130 :-)
    Et le plus intéressant, c'est que Delphi accepte les 3 versions avec un résultat identique, en choisissant donc par exemple la 2e ligne j'ai un code compatible dans les deux environnements,
    Mille mercis !

    Citation Envoyé par e-ric Voir le message
    @Jipété
    La classe TStream est abstraite, c'est dans les classes dérivées comme TFileStream qu'il faut chercher l'implémentation réelle.
    C'est tout ce que j'ai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    { THandleStream class }
      THandleStream = class(TStream)
      private
        FHandle: THandle;
      protected
        procedure SetSize(NewSize: Longint); override;
        procedure SetSize(const NewSize: Int64); override;
      public
        constructor Create(AHandle: THandle);
        function Read(var Buffer; Count: Longint): Longint; override;
        function Write(const Buffer; Count: Longint): Longint; override;
        function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
        property Handle: THandle read FHandle;
      end;
     
    { TFileStream class }
      TFileStream = class(THandleStream)
      Private
        FFileName : String;
      public
        constructor Create(const AFileName: string; Mode: Word);
        constructor Create(const AFileName: string; Mode: Word; Rights: Cardinal);
        destructor Destroy; override;
        property FileName : String Read FFilename;
      end;
    Citation Envoyé par e-ric Voir le message
    @Pascal Paul
    Je n'y avais pas pensé; c'est une piste à explorer. Mais cela me semble fort en chocolat quand même.
    @+
    Dans le petit matin ça nous réveillera

    Je coche mais on peut continuer à discuter.

    Bonne journée,

  12. #12
    Membre expert
    Avatar de e-ric
    Homme Profil pro
    Apprenti chat, bienfaiteur de tritons et autres bestioles
    Inscrit en
    Mars 2002
    Messages
    1 561
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Apprenti chat, bienfaiteur de tritons et autres bestioles

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 561
    Points : 3 951
    Points
    3 951
    Par défaut
    Je me suis planté avec ton prénom, désolé Paul.

    @+

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 12/04/2011, 15h05
  2. [SOAP][XML-RPC] Besoin d'explications sur le fonctionnement
    Par walid0577 dans le forum XML/XSL et SOAP
    Réponses: 1
    Dernier message: 01/05/2007, 18h52
  3. besoin d'explication sur le c++
    Par poporiding dans le forum MFC
    Réponses: 13
    Dernier message: 17/12/2005, 18h01
  4. Besoin d'explications sur un bout de code
    Par zizitop dans le forum C
    Réponses: 7
    Dernier message: 26/04/2005, 14h51
  5. Besoin d'explications sur float et l'élasticité !
    Par KneXtasY dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 14/01/2005, 15h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo