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

Delphi Discussion :

Transmettre un tableau dynamique par adresse


Sujet :

Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Développeur .NET
    Inscrit en
    Juin 2002
    Messages
    274
    Détails du profil
    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2002
    Messages : 274
    Par défaut Transmettre un tableau dynamique par adresse
    Salut,
    Je voudrais transmettre l'adresse d'un tableau dynamique d'une méthode à une autre ; c'est OK pour l'envoi mais comment créer un nouveau tableau seulement avec l'adresse d'un autre ?
    Pour être plus clair voici mon 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
    16
    17
    18
    19
    20
    21
    22
    procedure TForm1.Button1Click(Sender: TObject);
    var
      tab: TSingleDynArray;
      I: Integer;
    begin
      SetLength(tab, 1000);
     
      // Remplissage bidon
      for I := 0 to High(tab) do
        tab[I] := I; 
     
      SetTab(@tab, Length(tab));
    end;
     
    // Réception
    procedure TForm1.SetTab(TabAdress: Pointer; TabSize: Integer);
    var
      tabTemp: TSingleDynArray;
    begin
      SetLength(tabTemp, TabSize);
      @tabTemp:= SignalAdress;             // non autorisé !
    end;
    Le but est de créer une dll de traitement de données utilisable en C, je n'y arrive pas...
    Merci !

  2. #2
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 089
    Par défaut
    Si ton tableau ne contient pas de pointer, ni de string, ni d'objet, en gros tout ce qui est référéncé par pointeur, tu peux directement faire un CopyMemory, je pense qu'avec les singles pas de soucis ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CopyMemory(@tabTemp, SignalAdress, SizeOf(Single)*Length(SignalAdress));
    sinon essaye tout simplement de considéré ta fonction C avec ses pointeurs comme des Var en Delphi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure TForm1.SetTab(var TabAdress: TSingleDynArray; TabSize: Integer);
    cela devrait fonctionner, c'est souvent comme cela que les pointeurs de structure des api windows sont passés !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre éclairé
    Développeur .NET
    Inscrit en
    Juin 2002
    Messages
    274
    Détails du profil
    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2002
    Messages : 274
    Par défaut
    Le CopyMemory me génère des violations d'accès, c'est con ça me paraissait une bonne idée

    J'ai donc utilisé la méthode du TSingleDynArray, ça compile en Delphi il faut que je teste l'accès à la dll en C.

    cela devrait fonctionner, c'est souvent comme cela que les pointeurs de structure des api windows sont passés !
    Aurais-tu un exemple ? C'est dans les fichiers windows.pas, system.pas, etc ?

    En tout cas merci

  4. #4
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 089
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    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 : 14 089
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Windows
    procedure GlobalMemoryStatus(var lpBuffer: TMemoryStatus); stdcall;
    voilà, j'ai cherché var dans l'unité, c'est pas dur à trouver ...

    VOID GlobalMemoryStatus(

    LPMEMORYSTATUS lpBuffer // pointer to the memory status structure
    );


    Parameters

    lpBuffer

    Points to a MEMORYSTATUS structure in which information about current memory availability is returned. Before calling this function, the calling process should set the dwLength member of this structure.
    Maintenant, tu as alloué la mémoire avec de faire le copymemory, si tu fais du c, tu devrais y être habitué non ?

    as-tu essayé des variantes de syntaxes ?

    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  5. #5
    Membre Expert
    Avatar de LadyWasky
    Femme Profil pro
    Inscrit en
    Juin 2004
    Messages
    2 932
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 55
    Localisation : France, Hauts de Seine (Île de France)

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 932
    Par défaut
    L'adresse d'un tableau dynamique est le tableau lui-même, en effet, d'après l'aide Delphi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Les variables tableau dynamique sont implicitement des pointeurs
    Donc, là dedans...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var MonTableau: array of integer;
    MonTableau est une variable pointeur

    Donc, si tu as, admettons, cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    function Somme(A: array of integer):integer;
    Tu passes une adresse à ta fonction quand tu fais ceci :
    Reprenons donc ton 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
    16
    17
    18
    19
    20
    21
    22
    procedure TForm1.Button1Click(Sender: TObject);
    var
      tab: TSingleDynArray;
      I: Integer;
    begin
      SetLength(tab, 1000);
     
      // Remplissage bidon
      for I := 0 to High(tab) do
        tab[i] := I; 
     
      SetTab(@tab, Length(tab)); 
    end;
     
    // Réception
    procedure TForm1.SetTab(TabAdress: Pointer; TabSize: Integer);
    var
      tabTemp: TSingleDynArray;
    begin
      SetLength(tabTemp, TabSize);
      @tabTemp:= SignalAdress;             // non autorisé !
    end;
    à cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SetTab(@tab, Length(tab));
    ..tu transmet donc un pointeur sur un pointeur de tableau

    Et là, il râle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    @tabTemp:= SignalAdress;
    normal, d'un coté tu as un pointeur sur un tableau, de l'autre un pointeur sur un pointeur

    donc, ça, c'est un peu mieux, parce que celà fonctionne (on est d'accord, celà ne fait toujours pas ce que tu souhaite ):
    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
    procedure TForm1.Button1Click(Sender: TObject);
    var
      tab: TSingleDynArray;
      I: Integer;
    begin
      SetLength(tab, 1000);
     
      // Remplissage bidon
      for I := 0 to High(tab) do
        tab[i] := I; 
     
      SetTab(tab); 
    end;
     
    // Réception
    procedure TForm1.SetTab(Tableau: TSingleDynArray);
    var
      tabTemp: TSingleDynArray;
    begin
      tabTemp:= Tableau;
    end;
    On revient à l'aide Delphi, qui nous dit :
    pour faire une copie indépendante d'un tableau dynamique, vous devez utiliser la fonction Copy globale

    Du coup :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    procedure TForm1.SetTab(Tableau: TSingleDynArray);
    var
      tabTemp: TSingleDynArray;
    begin
      tabTemp:=Copy(Tableau); //Aide Delphi : Si S est un tableau dynamique,
                                           // vous pouvez omettre les paramètres 
                              //Index et Count,et Copy copie la totalité du tableau.
    end;
    Tout simplement

  6. #6
    Membre éclairé
    Développeur .NET
    Inscrit en
    Juin 2002
    Messages
    274
    Détails du profil
    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juin 2002
    Messages : 274
    Par défaut
    Merci pour toutes ces explications sur les tableaux, effectivement je faisais n'importe quoi
    Mon code ressemble donc à ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    procedure SetTab(Tableau: TSingleDynArray; TabSize: Integer); 
    var
      tabTemp: TSingleDynArray;
    begin
      SetLength(tabTemp, TabSize);
      tabTemp:= Copy(Tableau);
    end;
    Le SetLength n'est pas nécessaire pour une utilisation Delphi, mais je l'ai gardé (ainsi que le paramètre TabSize) pour une utilisation en C...
    D'ailleurs pour l'utiliser, ça marchera comme ci-dessous ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    // Fichier header de ma dll
    void SetTab(float * Tableau, int TabSize);
     
    // Utilisation ?
    float myTab[1000];
    SetTab(myTab, 1000);
    Non je ne fais pas de C et mes cours sont loin...

  7. #7
    Membre éclairé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Par défaut
    Bonjour

    Si j'ai bien compris, tu veux pouvoir utiliser ta fonction d'allocation en C ?

    Déjà il vaut mieux que se ne soit pas une fonction membre d'une classe Delphi (déjà en C++ faire une Dll utilisable en C++ avec des classes dedans c'est quasi impossible entre compilateur différents - et franchement difficile avec le même, selon la version, le mode de compilation ... ), parce que appeler une un classe Delphi en C (encore que C++Builder ...).

    Ensuite je suppose que ton type TSingleDynArray est un tableau dynamique Delphi (c'est-à-dire type TSingleDynArray : array of QuelqueChose; ). Or ce n'est pas qu'un simple pointeur :

    Citation Envoyé par waskol
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Les variables tableau dynamique sont implicitement des pointeurs
    Donc, là dedans...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var MonTableau: array of integer;
    MonTableau est une variable pointeur

    ATTENTION : cf. l'aide Delphi
    Les variables tableau dynamique sont implicitement des pointeurs et sont gérés par la même technique de comptage de références que celle utilisée pour les chaînes longues. Pour libérer un tableau dynamique, affectez nil à une variable qui référence le tableau ou transmettez la variable à Finalize
    Donc c'est une entité dont la gestion mémoire est automatique.
    Lorsque tu affectes un tableau dynamique A à un autre B, tu lui passes en fait sa référence ET tu diminues le compteur de référence de l'ancien B (si non à nil) en augmentant celui partagé alors entre A et B. Lorsqu'il arrive à zéro, le tableau est automatiquement libéré.

    ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    procedure TForm1.Button1Click(Sender: TObject);
    var Tab : array of Integer;
    begin
      SetLength(Tab,10000);
    end;// Tab est libéré !!!
    Code asm : 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
    Unit2.pas.29: SetLength(Tab,10000);
    push $00002710
    lea eax,[ebp-$04]
    mov ecx,$00000001
    mov edx,[$00464b28]
    call @DynArraySetLength
    add esp,$04
    Unit2.pas.30: end;
    xor eax,eax
    pop edx
    pop ecx
    pop ecx
    mov fs:[eax],edx
    push $00464b99
    lea eax,[ebp-$04]
    mov edx,[$00464b28]
    call @DynArrayClear             // <<--  ICI
    ret 

    Tu peux passer un tableau dynamique (et une string) à une fonction C qui ne les réalloue pas (car les infos sur le compteur de réf. et la taille sont codés en négatif par rapport au pointeur, donc le code C ne les voit pas), mais les allouer dans le code Delphi et les laisser au code C ...
    Soit ils seront désalloués avant d'être retournés, soit le code C sera incapable de les désallouer correctement ... (ou écriture d'un procédure de désallocation Delphi et cassage du mécanisme de référence, mais ca reste plutôt dangereux).

    Une solution : gérer un tableau comme en C (uniquement par pointeur)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    type
      PTableau = ^TTableau ;
      TTableau = array[0..0] of TMontype;
    [..]
      //puis utiliser
      GetMem
      ReallocMem
      FreeMem
      // ou utiliser malloc et free du C par extern ...
    Un exemple : TListe utilise un tableau généré comme cela (mais pour faire du Delphi seulement mieux vaut utiliser les tableaux dynamiques).

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

Discussions similaires

  1. [XL-2007] Prb création de Tableau dynamique par VBA
    Par jean bapt' dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 11/09/2012, 10h24
  2. [PDF] Transmettre un tableau dynamique en dpf
    Par Stu76 dans le forum Bibliothèques et frameworks
    Réponses: 2
    Dernier message: 18/01/2011, 13h58
  3. QTP : transmettre un tableau dynamique dans une action
    Par magfred03 dans le forum Autres
    Réponses: 0
    Dernier message: 03/05/2010, 15h12
  4. Transmettre un tableau PHP par formulaire
    Par Amaury_35 dans le forum Langage
    Réponses: 5
    Dernier message: 11/08/2009, 09h14
  5. [VBA-E]actualisation d'un tableau dynamique par macro
    Par illight dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 18/04/2006, 16h37

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