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 :

D6 : Problème avec un record en retour de fonction


Sujet :

Langage Delphi

  1. #1
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 193
    Points : 28 077
    Points
    28 077
    Par défaut D6 : Problème avec un record en retour de fonction
    Salut à tous, je rencontre un petit problème en Delphi 6, j'utilise un type record comme paramètre de retour d'une fonction
    J'aurais voulu qu'en cas d'erreur ou impossibilité de le renseigner, retourner un objet vide. Je pensais donc retourner un null, mais visiblement ça veut pas :

    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
     
      type
        toto = record
          bananne : integer;
          poire : integer;
        end;
     
    ...............................
     
      Function MaFonction() : toto;
      var
        ........
      Begin
        .........
        result := null;
        .........
      end;
    Je me ramasse le message d'erreur
    [DCC Erreur] Module.pas(636): E2010 Types incompatibles : 'MaFonction' et 'Variant'
    Il y a une solution, ou j'ai mal fait quelque chose ?


    PS : J'ai tenté avec nil aussi, mais là non plus ça passe pas.
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  2. #2
    Membre éclairé Avatar de alves1993
    Homme Profil pro
    Développeur Java/Dart/Javascript/Android (FullStack)
    Inscrit en
    Décembre 2012
    Messages
    222
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : Côte d'Ivoire

    Informations professionnelles :
    Activité : Développeur Java/Dart/Javascript/Android (FullStack)
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2012
    Messages : 222
    Points : 659
    Points
    659
    Par défaut
    tu à crée un enregistrement pas une classe donc l'erreur qui apparait est normal

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    type
        toto = class
          bananne : integer;
          poire : integer;
        end;
     
    function test() : toto ;
    begin
      result := nil ;
    end;
    pour un enregistrement qui accepte la valeur nil (qui est de type pointer) sa reste a voir
    Un geek ne vieillit pas, il se met à jour.

    Pour plus d'informations sur Android regarder la faq Android.
    Ensuite les tutoriels Android sont disponibles ici
    Pour les mecs, qui n'arrivent pas toujours à digérer le Javascript, Dart peut-être une solution pour vous.

  3. #3
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 193
    Points : 28 077
    Points
    28 077
    Par défaut
    Non ça ne passe pas non plus, avec nil, j'ai un message d'erreur semblable :
    [DCC Erreur] Module.pas(636): E2010 Types incompatibles : 'MaFonction' et 'Pointer'
    pardon, j'avais pas vu que tu l'avais passé en classe.

    La classe nécessite une instanciation, ce que je voudrais éviter. Mais bon, si j'ai pas le choix
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  4. #4
    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 445
    Points
    28 445
    Par défaut
    il serait plus logique de faire ceci

    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
     
    function test(var r: toto): Boolean;
    begin
      ...
      Result := False;
      ...
    end;
     
    var
      r:toto;
    begin
      if test(r) then
      begin
      end;
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  5. #5
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 193
    Points : 28 077
    Points
    28 077
    Par défaut
    J'y avais aussi pensé.

    Question subsidiaire : Ce module est, pour le moment en interne dans un logiciel, mais il n'est pas impossible qu'à terme il soit déporté en tant que dll, d'ou la raison d'essayer de faire quelque chose le plus indépendant possible.

    Dans ce cas, que vaut-il mieux utiliser, les records ou les classes, et vaut-il mieux les passer en paramètres var ou en retour de fonctions, sachant que ces types seront utilisés par le programme appelant lors de l'appel de ces fonctions.


    PS : Si j'en viens à la dll, elle sera d'abords utiliser par un programme delphi 6 mais avec l'évolution du logiciel, elle pourra être utiliser par d'autre techno, notamment en vb.net
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  6. #6
    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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par sevyc64 Voir le message
    J'y avais aussi pensé.

    Question subsidiaire : Ce module est, pour le moment en interne dans un logiciel, mais il n'est pas impossible qu'à terme il soit déporté en tant que dll, d'ou la raison d'essayer de faire quelque chose le plus indépendant possible.

    Dans ce cas, que vaut-il mieux utiliser, les records ou les classes, et vaut-il mieux les passer en paramètres var ou en retour de fonctions, sachant que ces types seront utilisés par le programme appelant lors de l'appel de ces fonctions.


    PS : Si j'en viens à la dll, elle sera d'abords utiliser par un programme delphi 6 mais avec l'évolution du logiciel, elle pourra être utiliser par d'autre techno, notamment en vb.net
    record en paramètre var c'est le plus adapté, dans d'autres langages ce sera un pointeur sur la structure, mais c'est pareil.

    allocation de la structure par l'appelant donc pas de problème de libération

    attention ! ne pas mettre de type dynamique dans la structure (string, tableau dynamique, objet ...)

    petite astuce, il est sécurisant d'ajouter un champ Size dans la structure qui contient sa taille, ça permet à la DLL de savoir ce qu'elle manipule

    autre astuce, en utilisant un "packed record" tu désactives l'alignement des champs (un byte occupe 1 seul octet et pas 4 donc 3 ignorés), ça facilite les choses, quitte à forcer toi même le padding qui ne dépend pas des options de compilation...par contre ça pollue éventuellement l'aide à la saisie

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    type
      toto = packed record
        Size: Integer;
        Val : Byte;
        Pad: array[1..3] of Byte; // fixe la taille de la structure en multiple de 4 octets
        Ofs: Integer;
      end;
    var
      r: toto;
    begin
      r.size := SizeOf(r); // indique à la DLL la taille de la structure, elle pourra vérifier sa cohérence
     
    end;
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  7. #7
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 193
    Points : 28 077
    Points
    28 077
    Par défaut
    Justement, le problème est bien qu'il y aura pas mal de string à passer.

    J'ai vu sur le web que soit il fallait utiliser une librairie Sharemem (ou son équivalent FastSharemem), soit utiliser une petite astuce qui est de déclarer les strings en ShortString. J'ai tenté la seconde solution, j'espère que ça ira.

    Quant à la taille, justement elle ne peut être connue à l'avance puisque elle dépendra du remplissage de chaque membre du record.


    Je crois que les Violations d'accès vont être mon cauchemar pendant quelques jours. Déjà que Delphi me les fait tout seul sans rien lui demander.
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  8. #8
    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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par sevyc64 Voir le message
    Justement, le problème est bien qu'il y aura pas mal de string à passer.

    J'ai vu sur le web que soit il fallait utiliser une librairie Sharemem (ou son équivalent FastSharemem), soit utiliser une petite astuce qui est de déclarer les strings en ShortString. J'ai tenté la seconde solution, j'espère que ça ira.

    Quant à la taille, justement elle ne peut être connue à l'avance puisque elle dépendra du remplissage de chaque membre du record.


    Je crois que les Violations d'accès vont être mon cauchemar pendant quelques jours. Déjà que Delphi me les fait tout seul sans rien lui demander.
    ShareMem c'est la fin de la compatibilité avec les autres langages

    le passage de chaînes entre EXE et DLL a été évoqué de nombreux fois ici et dans "Delphi 7 Studio" dont le chapitre concerné est en ligne chez Eyrolles
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #9
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 193
    Points : 28 077
    Points
    28 077
    Par défaut
    Ok, merci pour le lien.

    Mais tout ça me rassure pas.
    Si j'ai bien tout compris, il faudrait que je passe toutes mes chaines en PChar, avec, au moment de l'appel, une chaîne déjà initialisée (tout au moins réservée) à la taille nécessaire. Le problème étant que j'ai plusieurs records de la sorte dont un qui comporte 49 strings dont la taille de chacune ne sera connue qu'au moment exact du remplissage. Ce n'est donc pas jouable.

    J'imagine que de transformer mes records en classes ne va pas résoudre le problème de la pré-initialisation à une taille connue des strings

    Il va falloir donc que je trouve un autre système. Je voudrais pourtant éviter le passage par fichiers intermédiaires car c'est vraiment pas propre comme système.

    Je ne comprend pas pourquoi, depuis le temps que les dll existent, il n'a pas été trouvé une solution universelle pour utiliser les strings avec celle-ci. Ce n'est quand même pas un type de données si exotique que ça. Mais toujours la me***, quelque soit le langage.
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

  10. #10
    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 445
    Points
    28 445
    Par défaut
    Citation Envoyé par sevyc64 Voir le message
    Ok, merci pour le lien.

    Mais tout ça me rassure pas.
    Si j'ai bien tout compris, il faudrait que je passe toutes mes chaines en PChar, avec, au moment de l'appel, une chaîne déjà initialisée (tout au moins réservée) à la taille nécessaire. Le problème étant que j'ai plusieurs records de la sorte dont un qui comporte 49 strings dont la taille de chacune ne sera connue qu'au moment exact du remplissage. Ce n'est donc pas jouable.

    J'imagine que de transformer mes records en classes ne va pas résoudre le problème de la pré-initialisation à une taille connue des strings

    Il va falloir donc que je trouve un autre système. Je voudrais pourtant éviter le passage par fichiers intermédiaires car c'est vraiment pas propre comme système.

    Je ne comprend pas pourquoi, depuis le temps que les dll existent, il n'a pas été trouvé une solution universelle pour utiliser les strings avec celle-ci. Ce n'est quand même pas un type de données si exotique que ça. Mais toujours la me***, quelque soit le langage.
    ce n'est pas un problème de string c'est un problème d'allocation mémoire, ShareMem est la solution de Borland/Embarcadero pour partager un gestionnaire de mémoire...d'ailleurs dans COM tu des BSTR.

    que fais-tu de tes 49 chaines ? elles sont lues par qui est mise à jour par qui ? si c'est la DLL qui les alimente alors il est plus simple d'utiliser l'autre approche

    côté EXE

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    type
      TMonRecord = record
        Data1: PChar;
        Data2: PChar;
        Data3: PChar;
        Reserved: Integer;
      end;
     
    function GetRecord(var R: TMonRecord): Boolean; external 'madll.dll';
    procedure FreeRecord(const R:TMonRecord); external 'madll.dll';
    côté DLL
    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
     
    type
      TMonRecord = record
        Data: array[0..2] of PChar;
        Reserved: TStringList;
      end;
     
    function GetRecord(var R: TMonRecord): Boolean; 
    var
      Index: Integer;
    begin
      FillChar(R, SizeOf(R), 0);
      R.Reserved := TStringList.Create;
      R.Reserved.Add('un');
      R.Reserved.Add('deux');
      R.Reserved.Add('trois');
      for Index := 0 to 2 do R.Data[Index] := R.Reserved[Index]; // à vérifier...il ne faudrait pas que ce soit une chaîne temporaire mais bien un pointeur sur la chaîne stockée dans la stringlist
    end;
     
    procedure FreeRecord(const R: TMonRecord);
    begin
      R.Reserved.Free;
    end;
     
    procedure FreeRecord(const R:TMonRecord); external 'madll.dll';
    le principe est d'avoir entre l'EXE et la DLL des structures de même tailles mais contenant des informations différentes (Integer d'un côté TStringList de l'autre par exemple).

    la StringList permet ici de stocker les chaines présentées sous forme de PChar à l'exe, et l'objet sera détruit par FreeRecord()
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  11. #11
    Modérateur
    Avatar de sevyc64
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2007
    Messages
    10 193
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 193
    Points : 28 077
    Points
    28 077
    Par défaut
    Salut,

    J'étudierais plus précisément ton code demain, mais pour répondre à ta question, les chaines, ou plus exactement les record les contenant seront, la plupart du temps, lus dans des fichiers (de type ini) par la dll puis transmis à l'exe client. Mais j'ai quelques fonctions ou les records vont transiter dans le sens inverse, de l'exe vers la dll afin de créer/recréer les fichiers.
    Certes, en étudiant précisément les données qui transitent, je pourrais transformer certaines strings en leur vrai type (integer, boolean, etc....) mais de toute façon je ne pourrais pas le faire pour toutes car certaines, les principales en plus, sont du vrai texte dont le contenu et la taille réelle ne peut être connu à l'avance (nom, prénom, adresse et plein de chose comme ça).

    Pourquoi ne pas accéder aux fichiers directement depuis l'exe ? Cette fonctionnalité est à l'heure actuelle, totalement intégrée à l'exe, à l'arrache, un peu partout dans le code et sans modularité. Le problème est que, désormais, pour pouvoir utiliser cette fonctionnalité, on nous impose de faire certifier le logiciel par un organisme dédié avec comme contrainte que chaque modification du logiciel impose une recertification. Le logiciel étant en permanence en évolution, on ne peut pas se permettre de relancer une certification toutes les semaines (celle-ci pouvant durer entre 1 et 3 mois).
    Donc l'idée est de modulariser et de sortir cette fonctionnalité dans une dll (ou exe pilotable, mais ça revient au même) que l'on fera certifier une bonne fois pour toutes.

    L'alternative, comme initialement évoqué par le chef de projet, serait de passer par des fichiers intermédiaires, de type XML. Personnellement je trouve pas ça très judicieux, en terme de performance déjà, puis passer par du XML pour traiter du INI....
    C'est la raison pour laquelle j'étais parti sur une dll, mais, bien que ce n'est jamais simple de passer des strings à une dll, je ne le pensais pas si compliqué en Delphi (quoique c'est similaire avec les api windows).
    --- Sevyc64 ---

    Parce que le partage est notre force, la connaissance sera notre victoire

Discussions similaires

  1. Réponses: 7
    Dernier message: 27/04/2012, 10h09
  2. Réponses: 1
    Dernier message: 07/10/2010, 03h54
  3. Réponses: 1
    Dernier message: 07/02/2008, 21h40
  4. Problème avec le bouton Annuler de la fonction Inputbox
    Par r0main2b dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 05/06/2007, 19h48
  5. Réponses: 3
    Dernier message: 10/01/2006, 14h01

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