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 :

conversion type C++ vers Delphi


Sujet :

Langage Delphi

  1. #1
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 941
    Points : 1 946
    Points
    1 946
    Par défaut conversion type C++ vers Delphi
    Bonjour,

    J'ai une conversion à faire mais je ne trouve pas comment, voici le code C++ :

    Code cpp : 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
     typedef union __address
    	{
    		uint16_t value;
    		struct
    		{
    			uint8_t high;
    			uint8_t low;
    		} bytes;
    		struct __attribute__((packed))
    		{
    			uint8_t line:3;
    			uint8_t area:5;
    			uint8_t member;
    		} ga;
    		struct __attribute__((packed))
    		{
    			uint8_t line:4;
    			uint8_t area:4;
    			uint8_t member;
    		} pa;
    		uint8_t array[2];
    	} address_t;

    Pour l'union je sais faire, il suffit d'utiliser le case :
    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
     
    type
     
    Tbytes = record
      high : Byte;
      low : Byte;
    end;
     
    etc
     
    address_t = record
       ...
       case Integer of
          0: bytes : TBytes;
          1: ga : ..;
          2: pa : ...I;
       end;
       ...
    end;
    Ce que je ne sais pas traduire c'est le struct avec __attribute__((packed)) :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    struct __attribute__((packed))
    		{
    			uint8_t line:3;
    			uint8_t area:5;
    			uint8_t member;
    		} ga;

    que signifie les éléments de cette structure ? uint8_t line:3;

    que veut dire le ':3' et comment traduire __attribute__((packed)) en Delphi ?

    D'après mes recherches __attribute__((packed)) est utilisé pour minimiser l'espace mémoire utilisé

  2. #2
    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
    le suffixe indique le nombre de bits utilisés...tu ne peux pas le traduire directement sous Delphi

    alors je ne me souviens jamais de l'ordre, mais line prend 3 bits, et area 5, le tout fait donc un Byte

    tu peux utiliser des propriétés pour extraire les bits d'un champ privé

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    (*
    		struct __attribute__((packed))
    		{
    			uint8_t line:3;
    			uint8_t area:5;
    			uint8_t member;
    		} ga;
    *)
     
    type
      tga = record
      private
        flags: Byte;
        function getFlag(Index: Integer): Byte;
        procedure SetFlag(Index: Integer; Value: Integer);
       public
        member: Byte;
        property line index $03 read GetFlag write SetFlag;
        property area index $35 read GetFlag write SetFlag;
      end;
     
    // attention j'ai pas testé ! :)
    function tga.getFlag(Index: Integer): Byte;
    begin
      var pos := Index shr 4; // $03 => 0 et 3, $35 => 3 et 5
      var len := Index and $F;
      Result := (flags shr pos) and ((1 shl len) - 1);
    end;
     
    procedure tga.setFlag(Index: Integer; Value: Byte);
    begin
      var pos := Index shr 4; // $03 => 0 et 3, $35 => 3 et 5
      var len := Index and $F;
      Flags := flags and (255 - ((1 shl len) - 1) shl pos) or (value shl pos);
    end;

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 648
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 648
    Points : 10 619
    Points
    10 619
    Par défaut
    Le packed c'est pour l'alignement des données : alignement en mémoire, lien wikipedia
    En gros, le compilateur va faire en sorte de faire commencer les membres/ variables tous les 8 octets (ou 4) (en 64 bits) pour des questions de performance.

    Par exemple, si tu as 1 char (1 octet) (disons c) et 1 entier long (8 octets) (disons e) dans 1 structure.
    En théorie | c | e | e | e | e | e | e | e | e |, mais pour récupérer l'entier c'est la galère (il faut charger 2 octets, le 1ier retiré le char et le 2ième ne prendre que 1 bit)
    Alors soit le char est mis après | e | e | e | e | e | e | e | e | c | soit il y a alignement | c | | | | | | | | e | e | e | e | e | e | e | e |
    (c'est 1 réflexe des développeurs C de définir ses structures en organisant manuellement ses membres en fonction de leur taille octet : les + gros en premier, les + petit en dernier)

    Édit : packed sert à désactiver l'alignement.


    uint8_t line:3; c'est 1 notation pour prendre que 3 bits sur les 8 (1 octet)
    C'est pour "casser" des octets contiguës en plusieurs parties ou faire des drapeaux ("flags")

    Dans ton exemple uint8_t line:3; uint8_t area:5; dans 1 octet, tu as 2 valeurs : line (3 bits, valeur 0 à 7) et area (5 bits, valeur 0 à 31)
    Le packed sert sûrement à assurer que l'octet aura bien ces 2 valeurs.

    Édit : Cette technique permet à la fois d'optimiser la place (si c'est nécessaire mais en perdant des valeurs) et d'avoir la valeur avec juste 1 membre (s.line au lieu de ((val & 0xE0) >> 5) et s.area au lieu de (val & 0x1F))


    uint8_t ce sont les types de l'entête cstdint (c++)/ stdint.h (c) (<- lien cplusplus.com en anglais)
    En gros, ces types assurent le nombre d'octets utilisés. Parce que la taille en octet des types de base C/ C++ dépend de la plateforme (sauf char qui sera toujours 1 octet)

  4. #4
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 941
    Points : 1 946
    Points
    1 946
    Par défaut
    Merci à vous deux, je vais voir tout ça !

  5. #5
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Ensuite, tu n'es pas obligé de reproduire complètement le type address_t au complet

    TBytes, tu devrais éviter, c'est un type Delphi déjà existant

    Ceci sera amplement suffisant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    TKNX_Adresss = record
      bytes: record
        high : Byte;
        low : Byte;
      end;
    end;
    Et

    cemi_data->destination.bytes.high = (area << 3) | line; deviendra cemi_data.destination.bytes.high := (area shl 3) or line;


    printf("%2u.%2u.%3u ", a.pa.area, a.pa.line, a.pa.member); deviendra Format('%2u.%2u.%3u ', [a.bytes.high shr 3 (*pa.area*), a.bytes.high and $1F (*pa.line*), a.low (*pa.member*)]);

    J'ai bossé en Modbus via proconX, je te conseille de trouver un SDK plus haut niveau pour KNX, comme Falcon SDK ... en général, il y a des gens bien plus pointu qui travaille sur les protocoles de bus depuis des décennies fournissant des Wrapper suffisamment complets et surtout robustes.

  6. #6
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 941
    Points : 1 946
    Points
    1 946
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    J'ai bossé en Modbus via proconX, je te conseille de trouver un SDK plus haut niveau pour KNX, comme Falcon SDK ... en général, il y a des gens bien plus pointu qui travaille sur les protocoles de bus depuis des décennies fournissant des Wrapper suffisamment complets et surtout robustes.
    Merci pour ton aide et tes conseils !
    C'est justement parce que je n'ai pas trouvé de SDK que je m'intéresse au standard KNXnet/IP. Je me suis intéressé au Falcon SDK mais impossible de l'utiliser avec Delphi pourtant ils indiquent que cela est possible... Je leur ai envoyé un mail pour avoir plus de précision sur l'utilisation de leur SDK avec Delphi et leur réponse a été : aucune aide de leur part si je ne suis pas ou si je ne travaille pas pour un fabricant KNX... Et la documentation ne concerne que C#.

    Si tu connais d'autres SDK de plus haut niveau, je suis preneur !

  7. #7
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 563
    Points : 25 165
    Points
    25 165
    Par défaut
    Non, je ne suis plus du tout dans ce métier, j'ai vaguement fait un système d'Interphone mais bricolage, non standard


    C# DotNet, suffit que l'Interopérabilité COM soit activé !
    Facile à voir, suffit de l'installer, de voir si Delphi le voit dans Import de Bibliothèque de Type


    Pense que tu as un sacré chantier, exemple

    Et dans certains cas, tu peux utiliser une énumération et son ensemble comme masque binaire

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        struct
        {
          // Struct is reversed due to bit order
          uint8_t confirm:1; // 0 = no error, 1 = error
          uint8_t ack:1; // 0 = no ack, 1 = ack
          uint8_t priority:2; // 0 = system, 1 = high, 2 = urgent/alarm, 3 = normal
          uint8_t system_broadcast:1; // 0 = system broadcast, 1 = broadcast
          uint8_t repeat:1; // 0 = repeat on error, 1 = do not repeat
          uint8_t reserved:1; // always zero
          uint8_t frame_type:1; // 0 = extended, 1 = standard
        } bits;

    cela se traduit en Delphi par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    TKNX_cemi_service_control1_Enum = (
      knxcsccError,
      knxcscaAck,
      knxcscpHighOrNormal, knxcscpUrgentOrNormal,
      knxcscsbBroadcast,
      knxcscrDoNotRepeat,
      knxcscrdReservedNotUse,
      knxcscftStandard
    ;)
    TKNX_cemi_service_control1_Bits = set of TKNX_cemi_service_control1_Enum;
    Faudra vérifier l'ordre, c'est peut-être l'inverse, l'idée c'est d'associer une valeur à chaque bits, du bit 0 au bit 7

    Pour écrire

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    bits.confirm = 1;
    bits.ack = 1;
    bits.priority = 3; // normal
    bits.system_broadcast = 1;
    bits.repeat = 1;
    bits.reserved = 0;
    bits.frame_type = 1;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bits := [knxcsccNoError, knxcscpHighOrNormal, knxcscpUrgentOrNormal, knxcscsbBroadcast, knxcscrDoNotRepeat, knxcscftStandard];

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if (bits.priority == 0)
      {system}
    else if (bits.priority == 1)
      {high}
    else if (bits.priority == 2)
      {urgent/alarm}
    else if (bits.priority == 3)
      {normal}

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if (knxcscpHighOrNormal in bits) and not (knxcscpUrgentOrNormal in bits) then
      high
    else if not (knxcscpHighOrNormal in bits) and (knxcscpUrgentOrNormal in bits) then
      urgent/alarm
    else if (knxcscpHighOrNormal in bits) and (knxcscpUrgentOrNormal in bits) then
      normal
    else
      system

  8. #8
    Membre chevronné
    Avatar de free07
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2005
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ardèche (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 941
    Points : 1 946
    Points
    1 946
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    C# DotNet, suffit que l'Interopérabilité COM soit activé !
    Facile à voir, suffit de l'installer, de voir si Delphi le voit dans Import de Bibliothèque de Type
    Oui mais je n'ai pas précisé que je ne souhaite pas cibler windows mais les tablettes et les phones iOS et Android

    Citation Envoyé par ShaiLeTroll Voir le message
    Pense que tu as un sacré chantier
    Je sais, pour utiliser le Falcon SDK je pourrai me former à C# et utiliser Visual Studio mais je ne suis pas très chaud, changer d'environnement et langage juste pour un projet perso, cela ne m'intéresse pas vraiment.
    En fait, j'ai fait toute mon installation KNX ( uniquement lumières et volets roulant ) lorsque j'ai construit mon appart, ce n'est pas une grosse installation et mon projet se limite à celle-ci.
    Maintenant que j'ai un peu de temps libre, j'ai envie d'en consacrer une partie à la conception d'une petite supervision en me limitant à mon installation.

    Le plus gros du travail est en effet d'utiliser KNXnet/IP, si j'arrive à envoyer et recevoir des télégrammes KNX à partir de l'IP par l'intermédiaire de mon Interface IP/KNX N148, c'est gagné.
    J'ai une bonne expérience avec Builder C++, avant l'arrivée de la lib FMX je développais avec Builder et j'ai basculé sur Delphi depuis. Peut être devrais je envisager de revenir à Builder pour le faire directement en C++. Mais bon, si je peux utiliser Delphi, c'est mieux !

    En tout cas, merci pour tes exemples !

Discussions similaires

  1. Conversion fonction Javascript vers Delphi
    Par JustMe dans le forum Langage
    Réponses: 8
    Dernier message: 15/04/2021, 05h21
  2. Conversion type C vers Delphi
    Par castorcharly dans le forum Langage
    Réponses: 9
    Dernier message: 14/11/2016, 15h26
  3. Delphi 7, Conversion de type Shortstring vers int
    Par Marc_3 dans le forum Langage
    Réponses: 6
    Dernier message: 30/09/2013, 12h34
  4. conversion type Image vers tableau
    Par elektronik-17 dans le forum Débuter
    Réponses: 6
    Dernier message: 22/08/2008, 00h47
  5. Réponses: 1
    Dernier message: 11/05/2007, 18h18

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