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 C++ Discussion :

Signification de : "typedef void PortMidiStream;"


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Signification de : "typedef void PortMidiStream;"
    Bonsoir, j'espère que vous allez bien,
    je ne sais si je m'adresse à la bonne porte.
    Voici, je souhaite importer un bibliothèque avec C++ depuis une code avec Ada.
    Dans mon portmidi.h apparaît la description suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    typedef void PortMidiStream;
    Je voudrai savoir ce qu'il faut que je traduise avec Ada.
    S'il vous plaît ? Merci !

  2. #2
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Ce genre de déclaration est habituellement faite pour masquer une implémentation réelle, c'est à dire que tu vas passer des "PortMidiStream*" qui seront donc des "void*", le module utilisateur utilisant en général une structure interne (et privée) pour déréférencer le pointeur suivant le type correct.

    De mémoire, en Ada, ton "void*" devra être traduit en "Address" (paquetage System)... Par contre, pour le type "void" lui-même, je ne crois pas que ce soit possible : en Ada, on fait la distinction entre les fonctions et les procédures, et un tel type n'a aucune raison d'exister...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  3. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Le mot clé typedef ne sert en définitive qu'à donner un autre nom pour un type donné.

    Ainsi, avec le typedef que tu présente, chaque utilisation de PortMidiStream revient strictement au même que si tu remplaçait le terme par void.

    On peut donc se demander s'il y a un intérêt majeur à ce typedef, hormis s'il n'est jamais utilisé que sous la forme de pointeur, ce qui correspond à un void * nom_de_variable.

    En effet, un pointeur sur void peut être utilisé, en C (parce qu'on préfère l'éviter en C++) pour représenter, en définitive, un pointeur sur n'importe quoi, et de donner son sens réel à coup de transtypage.

    En C++ on préférera cependant souvent avoir recours au paradigme de programmation générique et à l'utilisation de fonctions et de classes template

    Quant à ta question de savoir comment traduire cela en Ada, je ne connais malheureusement pas assez ce langage pour t'orienter, mais les informations que je viens de te donner te fourniront peut être une piste de réflexion
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Invité
    Invité(e)
    Par défaut
    Merci Mac LAK, merci koala01,
    je doit utiliser une bibliothèque C++ a priori, et j'ai un soucis à propos de la valeur que peut prendre un tel objet ; Une System.Address, donc éventuellement, si celle-ci est initialiser par la function qui est sensée initialiser les accès à cette address ou si elle utlise l'adresse courant, c'est à dire n'importe laquelle.
    C'est une instruction tirée d'un portmidi.h sur un système Gnu/linux Debian.
    Merci encore.

    edit : Une question me préoccupe également, c'est si l'adresse n'est pas initialiser, comment je dois m'y prendre pour piocher la bonne case ?
    Dernière modification par Invité ; 11/08/2009 à 04h59.

  5. #5
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par jovalise Voir le message
    Une System.Address, donc éventuellement, si celle-ci est initialiser par la function qui est sensée initialiser les accès à cette address ou si elle utlise l'adresse courant, c'est à dire n'importe laquelle.
    C'est ça : tu devrais normalement avoir des fonctions qui vont te retourner un "PortMidiStream*", que tu remplaceras par un System.Address. Je te conseille toutefois, pour des raisons de lisibilité, de déclarer un type explicite, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Type PPortMidiStream is New System.Address ;
    Ainsi, entre le code C et Ada, tu n'as que l'étoile qui dégage, remplacée par un préfixe "P" (pour "Pointer").
    Si jamais tu vois passer un "PortMidiStream**" ou un "&PortMidiStream*" (passage par référence), tu devrais t'en sortir en mettant un "In Out" devant ton paramètre Ada.

    Si jamais ton code C/C++ utilise directement un PortMidiStream sans son étoile, par contre, c'est mal barré car cela ne devrait jamais se produire (dans les interfaces publiques du moins)... Si jamais c'est le cas, tu posteras tes fichiers .H ici, que l'on jette un œil.

    Citation Envoyé par jovalise Voir le message
    Une question me préoccupe également, c'est si l'adresse n'est pas initialiser, comment je dois m'y prendre pour piocher la bonne case ?
    Par défaut, vu que l'implémentation est masquée, tu ne devrais jamais te retrouver avec ce cas : quand tu vas "ouvrir" un flux MIDI, soit la fonction C/C++ te retournera la bonne valeur (alors considérée comme un handle opaque, un peu dans le genre d'un FILE*), soit elle prendra en référence une variable du bon type qu'elle initialisera (cas d'un PortMidiStream** ou d'un &PortMidiStream*).
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  6. #6
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Mac LAK Voir le message
    Je te conseille toutefois, pour des raisons de lisibilité, de déclarer un type explicite, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Type PPortMidiStream is New System.Address ;
    Ainsi, entre le code C et Ada, tu n'as que l'étoile qui dégage, remplacée par un préfixe "P" (pour "Pointer").
    Reçu !
    Si jamais tu vois passer un "PortMidiStream**" ou un "&PortMidiStream*" (passage par référence), tu devrais t'en sortir en mettant un "In Out" devant ton paramètre Ada.
    Comme dans cet appel :: ou midi est un PmStream kqui est un #define PMStream PortMidiStream...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     /* open output device -- since PortMidi avoids opening a timer
         when latency is zero, we will pass in a NULL timer pointer
         for that case. If PortMidi tries to access the time_proc,
         we will crash, so this test will tell us something. */
      Pm_OpenOutput(&midi, 
                    i, 
                    DRIVER_INFO,
                    OUTPUT_BUFFER_SIZE, 
                    (latency == 0 ? NULL : TIME_PROC),
                    (latency == 0 ? NULL : TIME_INFO), 
                    latency);
    Malheureusement, ou heureusement, c'est une fonction et tout les paramètre d'un fonction son en lecture seullement.
    Si jamais ton code C/C++ utilise directement un PortMidiStream sans son étoile, par contre, c'est mal barré car cela ne devrait jamais se produire (dans les interfaces publiques du moins)... Si jamais c'est le cas, tu posteras tes fichiers .H ici, que l'on jette un œil.
    Je vais voir !
    Par défaut, vu que l'implémentation est masquée, tu ne devrais jamais te retrouver avec ce cas : quand tu vas "ouvrir" un flux MIDI, soit la fonction C/C++ te retournera la bonne valeur (alors considérée comme un handle opaque, un peu dans le genre d'un FILE*), soit elle prendra en référence une variable du bon type qu'elle initialisera (cas d'un PortMidiStream** ou d'un &PortMidiStream*).
    [/quote]
    Tout a l'air bon, ... mais ça coince à l'exécution.
    Merci pour cette réponse en pleine nuit.


    edit : sur l'appel

  7. #7
    Invité
    Invité(e)
    Par défaut
    Pardon midi est un ptr sur un PmStream.

  8. #8
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par jovalise Voir le message
    Malheureusement, ou heureusement, c'est une fonction et tout les paramètre d'un fonction son en lecture seullement.
    Oui, mais quand tu passes l'adresse d'une variable, l'adresse en question est certes en lecture seule... Mais pas son contenu, qui peut être modifié. Normalement, les modificateurs "In Out" de l'Ada devraient régler le problème.

    Citation Envoyé par jovalise Voir le message
    Tout a l'air bon, ... mais ça coince à l'exécution.
    Il faut aussi respecter les conventions d'appel, l'ordre des paramètres, etc.
    Je n'ai jamais câblé du C/C++ sur de l'Ada, mais j'ai vu que tu avais déjà posté dans le forum ADA, où tu devrais trouver la bonne réponse.

    Il faut surtout vérifier, pour chaque type C de base, à quel type Ada il correspond : il faut qu'il soit du même genre, bien sûr, mais surtout de la même taille (cf. "'Size"). Au pire, imprimes ces tailles en Ada, puis en C, et vérifie que ce sont bien les mêmes.
    Il n'est pas toujours évident de faire les traductions, mais ça reste quelque chose de parfaitement faisable quand le langage permet l'importation de modules externes compilés dans d'autres langages.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  9. #9
    Invité
    Invité(e)
    Par défaut
    j'ai fait un truc qui me semble un peu propre...

    J'ai déclaré un type :

    T_PortMidiStream is
    record
    null;
    end record;

    instancié System.Address_To_Access_Conversions.

    Ca a l'air de fonctionner. je passe le Open() mais pas le Write().

  10. #10
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par jovalise Voir le message
    Ca a l'air de fonctionner. je passe le Open() mais pas le Write().
    Faudrait voir aussi ce que ça vaut : t'as des fonctions pour convertir un "System.Address" en entier afin de pouvoir l'afficher, histoire de voir si c'est cohérent ou pas. A savoir aussi qu'il m'est arrivé, sur certaines importations de fonctions (en Delphi, d'ailleurs) de devoir écrire un petit bout de code C pour "sniffer" le résultat réel, et voir si j'avais bien la même valeur en Delphi... Ce n'étaient que de simples fonctions C ayant le même prototype que les "vraies", mais qui affichaient sur la sortie standard la valeur des paramètres avant/après appel de la "vraie" fonction.

    Pour le write, faudrait voir le prototype de la fonction C aussi...
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  11. #11
    Invité
    Invité(e)
    Par défaut
    Yep ! Je vais regarder ce que je peu faire pour tracer un peu.

    le prototype de Pm_Write :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    PmError Pm_WriteShort( PortMidiStream *stream, PmTimestamp when, long msg);
    Merci encore Mal LAK, koala01 !

  12. #12
    Invité
    Invité(e)
    Par défaut
    Pour le moment j'obtien un Storage_Error Ada tout classique au Pm_Write, si je peu m'exprimer ainsi.

    Alors, j'ai des donnée à formater également et la .... Ca concerne cette partie de code :
    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
     
    /*
        Pm_Message() encodes a short Midi message into a long word. If data1
        and/or data2 are not present, use zero.
     
        Pm_MessageStatus(), Pm_MessageData1(), and
        Pm_MessageData2() extract fields from a long-encoded midi message.
    */
    #define Pm_Message(status, data1, data2) \
             ((((data2) << 16) & 0xFF0000) | \
              (((data1) << 8) & 0xFF00) | \
              ((status) & 0xFF))
    #define Pm_MessageStatus(msg) ((msg) & 0xFF)
    #define Pm_MessageData1(msg) (((msg) >> 8) & 0xFF)
    #define Pm_MessageData2(msg) (((msg) >> 16) & 0xFF)
    Tu y comprends quelque chose ?

  13. #13
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 51
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Par défaut
    Citation Envoyé par jovalise Voir le message
    le prototype de Pm_Write :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    PmError Pm_WriteShort( PortMidiStream *stream, PmTimestamp when, long msg);
    Rien n'est passé en écriture, si ce n'est la structure interne (et masquée) du PortMidiStream*... Par contre, le timestamp, lui, peut poser des soucis, surtout si c'est tiré direct de la CLib côté formatage.

    Citation Envoyé par jovalise Voir le message
    Alors, j'ai des donnée à formater également et la .... Ca concerne cette partie de code :
    Tu y comprends quelque chose ?
    Oui : cela transforme un triplet MIDI (Statut,Donnée1,Donnée2) en un seul entier de 32 bits.

    Pour ceci, le statut (8 bits) occupe l'octet de poids faible, la donnée 1 (8 bits) le deuxième octet de poids faible, et enfin la donnée 2 occupe les 16 bits de poids fort. C'est le but de la première macro de "construire" ce mot de 32 bits, tandis que les trois dernières macros font l'opération inverse (conversion d'un entier 32 bits en trois champs unitaires, une macro pour chaque champ).

    Tu dois pouvoir t'en sortir avec un Record compacté, il devra faire exactement 4 octets en taille. Sinon, tu peux faire l'équivalent en Ada, même si c'est un peu plus le bronx qu'en C à faire... Mais tu peux t'en sortir avec des additions / multiplications / modulos sans aucun problème.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  14. #14
    Invité
    Invité(e)
    Par défaut
    Pour le record de 32 bits;
    j'ai fait ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
     type T_Octet is range 0..255;
       for T_Octet'Size use 8;
       type T_D_Octet is range 0..32766;
       for T_D_Octet'Size use 16;
     
       type T_Message is
          record
             Status : T_Octet;
             data1 : T_Octet;
             Data2 : T_D_Octet;
          end record;
    Et j'affecte simplement comme ça :: Pm_Event.Message := (16#90#, 60,100);

    Le Timestamp est un long que je récupère de Pt_Time dans porttime.h qui va avec de portmidi.h. Ca devrait être bon là, mais toujours le Storage_Error.

  15. #15
    Invité
    Invité(e)
    Par défaut
    Arrgg, j'ai pas tout retenu...
    Dans ca doit être l'inverse en fait mon record ... C B A ? n'est-ce pas ?

  16. #16
    Invité
    Invité(e)
    Par défaut
    Je passe devant...

    J'ai fait ça finalement pour le type de message (exclu timestamp)
    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
     
     type T_Message is
          record
             Status : T_Octet;
             Data1 : T_Octet;
             Data2 : T_D_Octet;
          end record;
     
       for T_Message'Alignment use 2;
     
       for T_Message use
          record
             Status at 0 range 0..7;
             Data1 at 0 range 8..15;
             Data2 at 1 range 16..31;
          end record;
     
       for T_Message'Bit_Order use System.Low_Order_first;

  17. #17
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Attention, il s'agit en fait de trois octets, pas deux octets et un mot de 16 bits.

    De plus, en passant par un record, tu t'exposes à des problèmes d'endianness, non?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  18. #18
    Invité
    Invité(e)
    Par défaut
    Bonjour Médinoc,

    Pourrais-tu être un poil plus précis, Tu parle de ce que j'ai fait avec Ada, ou de la def initialement en C ?

  19. #19
    Invité
    Invité(e)
    Par défaut
    Pardon, il manque une partie du code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    type T_Octet is range 0..255;
       for T_Octet'Size use 8;
       type T_D_Octet is range 0..65535;
       for T_D_Octet'Size use 16;

  20. #20
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Pour les 3 octets, je parle du C. Pour le record et les problèmes qu'il peut poser je parle de ce que tu as fait en Ada.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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