FORUM DE DISCUSSION SUR LE LANGAGE PANORAMIC
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.
FORUM DE DISCUSSION SUR LE LANGAGE PANORAMIC

Développement d'applications avec le langage Panoramic
 
AccueilAccueil  RechercherRechercher  Dernières imagesDernières images  S'enregistrerS'enregistrer  MembresMembres  Connexion  
Derniers sujets
» bouton dans autre form que 0
Des DLL pour Panoramic ? Emptypar leclode Aujourd'hui à 13:59

» KGF_dll - nouvelles versions
Des DLL pour Panoramic ? Emptypar Klaus Aujourd'hui à 11:41

» Gestion d'un système client-serveur.
Des DLL pour Panoramic ? Emptypar Klaus Aujourd'hui à 10:23

» PANORAMIC V 1
Des DLL pour Panoramic ? Emptypar papydall Sam 4 Mai 2024 - 3:43

» Editeur EliP 6 : Le Tiny éditeur avec 25 onglets de travail
Des DLL pour Panoramic ? Emptypar Froggy One Jeu 2 Mai 2024 - 11:16

» @Jack
Des DLL pour Panoramic ? Emptypar Jack Mar 30 Avr 2024 - 20:40

» trop de fichiers en cours
Des DLL pour Panoramic ? Emptypar papydall Lun 29 Avr 2024 - 23:39

» Une calculatrice en une ligne de programme
Des DLL pour Panoramic ? Emptypar jean_debord Dim 28 Avr 2024 - 8:47

» Form(résolu)
Des DLL pour Panoramic ? Emptypar leclode Sam 27 Avr 2024 - 17:59

» Bataille navale SM
Des DLL pour Panoramic ? Emptypar jjn4 Ven 26 Avr 2024 - 17:39

» Les maths du crocodile
Des DLL pour Panoramic ? Emptypar jean_debord Jeu 25 Avr 2024 - 10:37

» Naissance de Crocodile Basic
Des DLL pour Panoramic ? Emptypar jean_debord Jeu 25 Avr 2024 - 8:45

» Dessine-moi une galaxie
Des DLL pour Panoramic ? Emptypar jjn4 Lun 22 Avr 2024 - 13:47

» Erreur END_SUB
Des DLL pour Panoramic ? Emptypar jjn4 Lun 22 Avr 2024 - 13:43

» Bug sur DIM_LOCAL ?
Des DLL pour Panoramic ? Emptypar papydall Dim 21 Avr 2024 - 23:30

Navigation
 Portail
 Index
 Membres
 Profil
 FAQ
 Rechercher
Rechercher
 
 

Résultats par :
 
Rechercher Recherche avancée
Mai 2024
LunMarMerJeuVenSamDim
  12345
6789101112
13141516171819
20212223242526
2728293031  
CalendrierCalendrier
Le Deal du moment :
Réassort du coffret Pokémon 151 ...
Voir le deal

 

 Des DLL pour Panoramic ?

Aller en bas 
+2
Minibug
jean_debord
6 participants
Aller à la page : 1, 2  Suivant
AuteurMessage
jean_debord

jean_debord


Nombre de messages : 1250
Age : 69
Localisation : Limoges
Date d'inscription : 21/09/2008

Des DLL pour Panoramic ? Empty
MessageSujet: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyDim 12 Déc 2021 - 9:25

Je suis en train de modifier FBCroco afin qu'il puisse produire des DLL utilisables par Panoramic.

Je profite de l'occasion pour vous demander si les règles d'utilisation des DLL dans Panoramic sont toujours les mêmes, à savoir :

Code:

1. La DLL est chargée en mémoire par l'instruction :

dll_on "xxx.dll"

où xxx.dll est le nom de la bibliothèque. Quand la DLL n'est plus nécessaire, la mémoire peut être libérée par l'instruction dll_off

2. La syntaxe d'appel d'une fonction de DLL est de la forme :

result% = dll_calln("DllFunctionName", par1%, ..., parn%)

où n est un entier de 0 à 6 qui représente le nombre de paramètres passés à la fonction. Il y a en fait 7 routines différentes :

dll_call0("DllFunctionName")
dll_call1("DllFunctionName", par1%)
dll_call2("DllFunctionName", par1%, par2%)
..........................................

Le premier paramètre est une chaîne contenant le nom de la fonction appelée. Il est suivi par les paramètres de la fonction, qui sont théoriquement de type entier mais peuvent être des adresses, ce qui permet de passer des nombres réels ou des chaînes de caractères (voir paragraphe 3).

Notez aussi que :

* PANORAMIC ne peut appeler que des fonctions dans une DLL, pas de sous-programmes.

* Toute fonction appelée par dll_call doit retourner une valeur entière.

3. Les paramètres entiers peuvent être passés par valeur ou par référence. Dans ce dernier cas, on utilise la fonction adr() de PANORAMIC.

4. Les nombres réels sont obligatoirement passés par référence. Il en est de même pour les chaînes de caractères. Dans ce dernier cas cependant, le paramètre de la fonction appelée doit être un pointeur sur une chaîne à zéro terminal.

5. Les chaînes de caractères passées aux fonctions de la DLL doivent être dimensionnées à une longueur suffisante dans le programme appelant. C'est particulièrement important si la chaîne est modifiée par la DLL, car alors sa longueur peut varier.

6. Au stade actuel du développement de PANORAMIC, aucun tableau ne peut être passé, ni par valeur ni par référence avec adr().

7. L'appel des fonctions doit se faire selon la convention stdcall.

8. Le nom de la fonction appelée ("DllFunctionName") doit respecter les majuscules et les minuscules.

Je sais qu'il y a un nouveau mot-clé LIBRARY mais je ne le trouve pas dans ma version de Panoramic (0.9.29i11)
Revenir en haut Aller en bas
http://www.unilim.fr/pages_perso/jean.debord/index.htm
Minibug

Minibug


Nombre de messages : 4566
Age : 57
Localisation : Vienne (86)
Date d'inscription : 09/02/2012

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyDim 12 Déc 2021 - 11:33

Bonjour Jean,

En voilà une bonne idée. Je pense que Jack ou Klaus pourront te renseigner...

Concernant LIBRARY voici ce que disait Jack sur ce fil de discussion.

Bonne journée et à bientôt. Wink
Revenir en haut Aller en bas
http://gpp.panoramic.free.fr
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyDim 12 Déc 2021 - 17:26

Dans les conventions d'appel d'une DLL, tout est correct, sauf:
Citation :
6. Au stade actuel du développement de PANORAMIC, aucun tableau ne peut être passé, ni par valeur ni par référence avec adr().
En réalité, tu peux faire:
Code:
dim entiers%(10), flottants(15), res%
...
res% = dll_call2("TestDesTableaux",adr(entier%),adr(flottant))

La fonction TestDesTableaux recevra alors les adresses de premiers éléments des deux tableaux, à savoir l'adresse des données de entiers%(0) et flottant(0). Et les autres éléments sont rangés juste aprèsn sans parasites intermédiaire et sans coupures.

On peut même faire cela avec un tableau à 2 ou plusieurs dimensions. Cependant, seule l'adresse du premier élément est passée:
Code:
dim entiers2%(5,20), res%
...
res% = dll_call1("AutreTest",adr(entiers2%))
c'est l'adresse de entiers%(0,0) qui et passée.

On ne peut pas passer l'adresse d'un tableau de chaînes de caractères.

Et adr(s$) donne l'adresse d'une variable STRING en Delphi. A cette adresse, on trouve un pointeur vers le premier caractère des données. Avec l'offset -2, on a la longueur de la chaîne (peu utile car terminée par 0) et avec -4, on a le référence count.

Pour mapart, j'utilise les routines auxiliaires suivantes:
Code:
// fonction compatible avec la version compilée de PANORAMIC
//   par = identifiant de destination   soit ADR(s$)    soit HANDLE(memo%)
// Cette fonction prend des données string à partit d'un sgtring Panoramic,
// mais aussi le contenu d'un MEMO ou d'un LIST dont on a passé le handle en paramètre,
// et elle gère les particularités de Panoramic compilé.
  function GetStringFromPanoramic(par: integer): string;
  var
    n, Len, cnt, i: integer;
    memo: TMemo;
    lb: TListBox;
    s1, s2: string;
    control: TWinControl;
    pb: pbyte;
    pi: pinteger;

    function GetClassName(Handle: THandle): String;
    var
      Buffer: array[0..MAX_PATH] of Char;
    begin
      Windows.GetClassName(Handle, @Buffer, MAX_PATH);
      Result := String(Buffer);
    end;

  begin
    result := '';
    if par=0 then exit;
    try
      memo := TMemo(par);
      if memo.ClassName='TMemo' then begin
        result := memo.Text;
        exit;
      end;
    except
    end;

    try
      if GetClassName(par)='TMemo' then begin

        Len := SendMessage(par, WM_GETTEXTLENGTH, 0, 0);
        if Len>0 then begin
          SetLength(s1, Len+1);
          Len := SendMessage(par, WM_GETTEXT, Len+1, LPARAM(PChar(s1)));
          delay(100);
          SetLength(s1, Len);
        end;

        result := Trim(s1);
        exit;
      end;
    except
    end;

    try
      if GetClassName(par)='TListBox' then begin

        cnt := SendMessage(par, LB_GETCOUNT, 0, 0);
        s1 := '';
        if cnt<>LB_ERR then begin
          for i:=0 to cnt-1 do begin
            s2 := '';
            Len := SendMessage(par, LB_GETTEXTLEN, i, 0);
            if Len>0 then begin
              SetLength(s2, Len+1);
              SendMessage(par, LB_GETTEXT, i, LPARAM(PChar(s2)));
              delay(100);
              s1 := s1 + Trim(s2) + #13#10;
            end;
          end;
        end;

        result := Trim(s1);
        exit;
      end;
    except
    end;

    if PCompiledMode then begin
      cnt := 0;
{$if StringParameterMethod=1}
      pb := pbyte(par);                         // méthode V1 (Jack): ADR(s$) pointe vers l'adresse du premier caractère
{$else}
      if pinteger(par)^<>0 then begin
        pb := pbyte(pinteger(par)^);              // méthode V2 (Jack): ADR(s$) pointe vers un mot contenant l'adresse du premier caractère
{$ifend}
        while pb^<>0 do begin
          inc(pb);
          inc(cnt);
        end;
      end;
      SetLength(result,cnt);
      if cnt>0 then begin
        pb := pbyte(pinteger(par)^);
        for i:=1 to cnt do begin
          result[i] := chr(pb^);
          inc(pb);
        end;
      end;
    end else begin
      result := pstring(par)^;
    end;
  end;

// procédure compatible avec la version compilée de PANORAMIC
//   s   = string (éventuellement multi-ligne) à envoyer à Panoramic
//   par = identifiant de destination   soit ADR(s$)    soit HANDLE(memo%) soit handle(list%)
  procedure CopyStringToPanoramic(s: string; par: integer);
  var
    p1, p2: pchar;
    n, p: integer;
    memo: TMemo;
    s1, s2: string;
    control: TWinControl;
    pi, po: pbyte;
    zero: byte;

    function GetClassName(Handle: THandle): String;
    var
      Buffer: array[0..MAX_PATH] of Char;
    begin
      Windows.GetClassName(Handle, @Buffer, MAX_PATH);
      Result := String(Buffer);
    end;

  begin
    if par=0 then exit;
    try
      memo := TMemo(par);
      if memo.ClassName='TMemo' then begin
        s1 := s;
        memo.Text := trim(s1+' ');
        exit;
      end;
    except
    end;

    try
      if GetClassName(par)='TMemo' then begin
        s1 := s;
        SendMessage(par,WM_SETTEXT,0,integer(pchar(s1)));
        exit;
      end;
    except
    end;

    try
      if GetClassName(par)='TListBox' then begin
        SendMessage(par,LB_RESETCONTENT,0,0);
        s1 := s + #13#10;
        while s1<>'' do begin
          p := pos(#13#10,s1);
          if p>0 then begin
            s2 := LeftStr(s1,p-1);
            s1 := MidStr(s1,p+2,Length(s1));
            SendMessage(par,LB_ADDSTRING,0,integer(pchar(s2)));
          end;
        end;
        if s1<>'' then SendMessage(par,LB_ADDSTRING,0,integer(pchar(s1)));
        exit;
      end;
    except
    end;

    zero := 0;
    p1 := @zero;
    n := length(s);
    if n>0 then p1 := @s[1];
    if PCompiledMode then begin
      // mode compilé
      pi := pbyte(@s[1]);
{$if StringParameterMethod=1}
      po := pbyte(par);                         // méthode V1 (Jack): ADR(s$) pointe vers l'adresse du premier caractère
{$else}
      po := pbyte(pinteger(par)^);              // méthode V2 (Jack): ADR(s$) pointe vers un mot contenant l'adresse du premier caractère
{$ifend}
      while po^<>0 do begin
        if pi^<>0 then begin
          po^ := pi^;
          inc(po);
          inc(pi);
        end else begin
          po^ := 32;
          inc(po);
        end;
      end;
    end else begin
      //mode interprété
      if n>0 then p1 := pchar(@s[1]);
      p2 := pchar(pinteger(par)^);
      while p2^<>#0 do begin
        if n>0 then begin
                 if p1<>#0 then p2^ := p1^
                           else dec(p2);
               end else begin
                 p2^ := #32;
               end;
        inc(p1);
        inc(p2);
        dec(n);
      end;
    end;
  end;

// Cette procédure écrit une chaîne de caractères dans un sgtring Panoramic en le remplaçant partiellement
  procedure CopyStringOverPanoramicString(sIn: string; offs,sOut: integer);
  var
    cnt: integer;
    pi, po: pbyte;
  begin

    if PCompiledMode then begin
      cnt := 0;
      pi := pbyte(@sIn[1]);
{$if StringParameterMethod=1}
      po := pbyte(sOut+offs);
{$else}
      if sIn<>'' then begin
        po := pbyte(pinteger(sOut)^+offs);
{$ifend}
        while (pi^<>0) and (po^<>0) do begin
          po^ := pi^;
          inc(pi);
          inc(po);
        end;
      end;
    end else begin
      pi := pbyte(@sIn[1]);
      po := pbyte(pinteger(sOut)^+offs);
      while (pi^<>0) and (po^<>0) do begin
        po^ := pi^;
        inc(pi);
        inc(po);
      end;
    end;


  end;
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
jean_debord

jean_debord


Nombre de messages : 1250
Age : 69
Localisation : Limoges
Date d'inscription : 21/09/2008

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyLun 13 Déc 2021 - 10:11

Merci pour vos réponses !

Je vais tester le passage des tableaux.

En attendant, voici un exemple avec les chaines de caractères.

Code de la DLL en FBCroco :

Code:

function strcmp% (a$, b$)
' Comparaison de 2 chaines de caracteres
  
  if a = b then
    return 0
  elseif a > b then
    return 1
  else
    return -1
  end_if
end_function

Résultat de la traduction en FreeBASIC ( avec la future version de FBCroco ! )

Code:

extern "Windows-MS"

function strcmp(byref p_a as zstring ptr, byref p_b as zstring ptr) as long export
  dim as string a = *p_a
  dim as string b = *p_b

' Comparaison de 2 chaines de caracteres
  
  if a = b then
    return 0
  elseif a > b then
    return 1
  else
    return -1
  end if

  *p_a = a
  *p_b = b
end function

La DLL compilée ainsi qu'un programme test en Panoramic sont disponibles sur mon WebDav (dossier FBCroco, fichier strcmp.zip)
Revenir en haut Aller en bas
http://www.unilim.fr/pages_perso/jean.debord/index.htm
jean_debord

jean_debord


Nombre de messages : 1250
Age : 69
Localisation : Limoges
Date d'inscription : 21/09/2008

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyMar 14 Déc 2021 - 16:57

Exemple avec un tableau d'entiers :

Code de la DLL en FreeBASIC :

Code:

extern "Windows-MS"

function init_array (p as long ptr, byval n as long) as long export

  for i as long = 0 to n
    p[i] = i
  next i

  return n + 1  ' Nb d'elements
end function

end extern

Programme d'appel en Panoramic :

Code:

dll_on "C:\FBCroco\exemples\lib\panoramic\array.dll"

dim a%(10), res%, i%

res% = dll_call2("init_array", adr(a%), 10)

for i% = 0 to 10
  print a%(i%)
next i%  

print : print res%, " elements"

end

On passe un pointeur, d'où le changement de notation en FreeBASIC : p[i] au lieu de p(i)

Si l'on veut garder la notation habituelle, soit p(i), dans le code FBCroco, il faudra prévoir un mécanisme de traduction.
Revenir en haut Aller en bas
http://www.unilim.fr/pages_perso/jean.debord/index.htm
papydall

papydall


Nombre de messages : 7002
Age : 73
Localisation : Moknine (Tunisie) Entre la chaise et le clavier
Date d'inscription : 03/03/2012

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyMer 15 Déc 2021 - 2:40

Merci Jean et bon courage pour la suite!
Revenir en haut Aller en bas
http://papydall-panoramic.forumarabia.com/
jean_debord

jean_debord


Nombre de messages : 1250
Age : 69
Localisation : Limoges
Date d'inscription : 21/09/2008

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyJeu 16 Déc 2021 - 16:44

Merci papydall Smile

Du courage, il m'en faut car je n'arrive pas à faire la même chose avec un tableau à deux dimensions.

Code de la DLL :

Code:

extern "Windows-MS"

function init_array (p as long ptr, byval n1 as long, byval n2 as long) as long export

  for i as long = 0 to (n1 + 1) * (n2 + 1) - 1
    p[i] = i
  next i

  return (n1 + 1) * (n2 + 1)  ' Nb d'elements
end function

end extern

Programme d'appel en Panoramic :

Code:

dll_on "C:\FBCroco\exemples\lib\panoramic\array.dll"

dim a%(3,4), res%, i%, j%
                                                                      
res% = dll_call3("init_array", adr(a%), 3, 4)

for i% = 0 to 3
  for j% = 0 to 4
    print a%(i%,j%)
  next j%
  print  
next i%
  
print : print res%, " elements"

end

Seule la première ligne du tableau a% est initialisée.
Revenir en haut Aller en bas
http://www.unilim.fr/pages_perso/jean.debord/index.htm
Marc

Marc


Nombre de messages : 2389
Age : 63
Localisation : TOURS (37)
Date d'inscription : 17/03/2014

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyJeu 16 Déc 2021 - 17:24

Bonjour Jean,

Lorsque j’avais fait des essais, pour un tableau d’entiers (% en Panoramic),
La première ligne du tableau était à l’adresse adr(a%)
La deuxième ligne à l’adresse adr(a% + 880)
La troisième ligne à l’adresse adr(a%+1760)
Etc

Avec la version 0.9.29i9 de Panoramic.





Revenir en haut Aller en bas
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyJeu 16 Déc 2021 - 17:28

Citation :
Du courage, il m'en faut car je n'arrive pas à faire la même chose avec un tableau à deux dimensions.

Ben, c'est normal... Relis les contraintes que j'ai énoncé dans ma première réponse à ta question innitiale. On ne peut en aucun cas transmettre un tableau en deux dimensions. Tout simplement parce que l'allocation de mémoire pour des différente colonnes ne se suivent pas. Chaque colonne est mémorisée à part, de façon non prévisible.

Pire; la position des données en mémoire peut changer dynamiquement, ainsi que cellle d'une variable simple dont on a âssé l'adresse ! Il est donc impossible de mémoriser une adresse d'une variable Panoramic dans une variable interne à la DLL et espérer qu'ultérieurement, les données se trouvent au même endroit. Violation de mémoire assurée.
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyJeu 16 Déc 2021 - 17:38

@Marc:
C'est un effet aléatoire. Tout dépend, d'une part de la version de Panoramic, et d'autre part, de l'affectation de valeurs à ds variables de type string dont la déclaration se situe "devant" la déclaration du tableau. Le gestionnaire de mémoire de Delphi (langage dans lequel Panoramic est réalisé) réaffecte ses zones mémoire à sa guise, et les adresses virtuelles changent donc, même si les données n'ont pas changé. Si, en plus, on utilise la possibilité de redimensionner un tableau en Panoramic, alors là, tu imagines la salade...

Non. Le principe et simple et tient en 2 règles:

1. seule les variables simples de type entier, flottant ou string peuvent être passées par ADR(), ainsi que les tableaux à une seule dimension de type entier ou flottant. Techniquement, on peut aussi passer un tableau à une seule dimension de type string, mais l'accès aux données est nettement plus complique, car ce qui est mémorisé "en continu", ce sont les "descripteurs" des strings représentant les cellules et non les cellules elles-même.

2. l'adresse d'une variable n'est valable que pendant l'exécution de la fonction DLL appelée. Il ne sert à rien de vouloir mémoriser une telle adresse dans une variable persistante (globale) à l'intérieur de la DLL pour la réutiliser plus tard - ces adresses virtuelles peuvent changer de fa)on imprévisible suite à des actions du gestionnaire de mamoire de Delphi.

Tout non-respect de ces deux règles conduit, au mieux, à des données fantaisistes, mais plus probablement à des violation de mémoire, même en lecture. Je me suis assez cassé les dents sur ces problèmes pour être sûr de ce que j'avance.
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyJeu 16 Déc 2021 - 18:15

Complément d'information:

Ce qui ne change pas, ce sont les handles des objets. Si je dois mémoriser de façon persistante un lien avec des données de Panoramic à l'intérieur d'une DLL, j'utilise le handle d'un objet EDIT, MEMI ou LIST. Le handle de ces objets ne change pas (à condition, bien entendu, de ne pas faire DELETE sur ces objets...). Dans la DLL, je peux librement récupérer le contenu de ces objets et je peux le modifier ou remplacer, dans aucun problème d'allocation de mémoire.

Pourquoi ? C'est parce que Windows se charge dans ce cas des allocations de mémoire, pas Delphi.
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Marc

Marc


Nombre de messages : 2389
Age : 63
Localisation : TOURS (37)
Date d'inscription : 17/03/2014

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyVen 17 Déc 2021 - 1:09

Merci Klaus pour ces informations.
Revenir en haut Aller en bas
Minibug

Minibug


Nombre de messages : 4566
Age : 57
Localisation : Vienne (86)
Date d'inscription : 09/02/2012

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyVen 17 Déc 2021 - 8:11

Ah oui effectivement cela n'est pas aussi simple qu'il y parait !

Bon courage pour la suite Jean... Wink
Revenir en haut Aller en bas
http://gpp.panoramic.free.fr
jean_debord

jean_debord


Nombre de messages : 1250
Age : 69
Localisation : Limoges
Date d'inscription : 21/09/2008

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyVen 17 Déc 2021 - 8:27

Klaus a écrit:

1. seule les variables simples de type entier, flottant ou string peuvent être passées par ADR(), ainsi que les tableaux à une seule dimension de type entier ou flottant.

Merci Klaus. C'est parfaitement clair.

Je vais dans un premier temps m'en tenir aux variables simples. Ensuite j'ajouterai peut-être les tableaux numériques à 1 dimension.
Revenir en haut Aller en bas
http://www.unilim.fr/pages_perso/jean.debord/index.htm
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyVen 17 Déc 2021 - 10:23

Voici coment lire et écrire un tableau d'entiers ou de flottants:
Code:
// copier un tableau de type integer de Panoramic dans un tableau dynamique Delphi dans la DLL
function GetIntegerArrayFromPanoramic(aIntegerArray: pinteger; nDimension: integer): integer; stdcall; export;
var
  IntegerArray: array of Integer;
  i: integer;
  pi: pinteger;
begin
  result := -1;
  try
    if aIntegerArray=nil then exit;            // il faut au moins une adresse
    if nDimension<0 then exit;                // il faut une dimenion Panoramic valide
    SetLength(IntegerArray,nDimension+1);      // affecter la mémoire
    pi := aIntegerArray;                      // boucle de lecture
    for i:=0 to nDimension do begin
      IntegerArray[i] := pi^;                  // ccpier un élément
      inc(pi);                                // ajuster le pointeur
showmessage(format('%d: %d',[i,IntegerArray[i]]));  // juste pour montrer le résultat - ligne à supprimer !
    end;
    result := 0;
  except
  end;
end;
exports GetIntegerArrayFromPanoramic;

// copier un tableau de type integer d'un tableau dynamique Delphi dans la DLL vers un tableau dans Panoramic
function SetIntegerArrayFromPanoramic(aIntegerArray: pinteger; nDimension: integer): integer; stdcall; export;
var
  IntegerArray: array of Integer;
  i: integer;
  pi: pinteger;
begin
  result := -1;
  try
    if aIntegerArray=nil then exit;                  // il faut au moins une adresse
    if nDimension<0 then exit;                      // il faut une dimenion Panoramic valide

    // les 2 lignes suivantes sont là pour "simuler" un tableau existant dans la DLL...
    SetLength(IntegerArray,nDimension+1);            // affecter la mémoire
    for i:=0 to nDimension do IntegerArray[i] := i*2;

    if nDimension>=Length(IntegerArray) then exit;  // trop de données demandées ?
    pi := aIntegerArray;                            // boucle d'écriture
    for i:=0 to nDimension do begin
      pi^ := IntegerArray[i];                          // ccpier un élément
      inc(pi);                                        // ajuster le pointeur
showmessage(format('%d: %d',[i,IntegerArray[i]]));  // juste pour montrer le résultat - ligne à supprimer !
    end;
    result := 0;
  except
  end;
end;
exports SetIntegerArrayFromPanoramic;

// copier un tableau de type float de Panoramic dans un tableau dynamique Delphi dans la DLL
function GetFloatArrayFromPanoramic(aFloatArray: pfloat; nDimension: integer): integer; stdcall; export;
var
  FloatArray: array of double;
  i: integer;
  pf: pfloat;
begin
  result := -1;
  try
    if aFloatArray=nil then exit;              // il faut au moins une adresse
    if nDimension<0 then exit;                // il faut une dimenion Panoramic valide
    SetLength(FloatArray,nDimension+1);        // affecter la mémoire
    pf := aFloatArray;                        // boucle de lecture
    for i:=0 to nDimension do begin
      FloatArray[i] := pf^;                      // ccpier un élément
      inc(pf);                                  // ajuster le pointeur
showmessage(format('%d: %f',[i,FloatArray[i]]));  // juste pour montrer le résultat - ligne à supprimer !
    end;
    result := 0;
  except
  end;
end;
exports GetFloatArrayFromPanoramic;

// copier un tableau de type float d'un tableau dynamique Delphi dans la DLL vers un tableau dans Panoramic
function SetFloatArrayFromPanoramic(aFloatArray: pfloat; nDimension: integer): integer; stdcall; export;
var
  FloatArray: array of double;
  i: integer;
  pf: pfloat;
begin
  result := -1;
  try
    if aFloatArray=nil then exit;                    // il faut au moins une adresse
    if nDimension<0 then exit;                      // il faut une dimenion Panoramic valide

    // les 2 lignes suivantes sont là pour "simuler" un tableau existant dans la DLL...
    SetLength(FloatArray,nDimension+1);              // affecter la mémoire
    for i:=0 to nDimension do FloatArray[i] := i*2.002;

    if nDimension>=Length(FloatArray) then exit;    // trop de données demandées ?
    pf := aFloatArray;                              // boucle de lecture
    for i:=0 to nDimension do begin
      pf^ := FloatArray[i];                            // ccpier un élément
      inc(pf);                                        // ajuster le pointeur
showmessage(format('%d: %f',[i,FloatArray[i]]));  // juste pour montrer le résultat - ligne à supprimer !
    end;
    result := 0;
  except
  end;
end;
exports SetFloatArrayFromPanoramic;

Note importante:
Le code Delphi d'une DLL n'a AUCUN moyen de détecter la dimension d'un tableau Panioramic passé en paramètre. Il faut donc l'indiquer à la fonction sous forme d'un paramètre supplémentaire.

On peut bien sûr tenter de parcourir la table des symboles de Panoramic pour trouver cette information. Problème: la structure de cette table des symboles est susceptible de varier selon les versions de PAnoramic.

Ceci est donc à évirer. Ceci dit, il y a moyen d'y arriver pour une version donnée de Panormic. Voici une fonction qui m'a servi à localiser le début de la table de symboles de Panoramic:
Code:
// trouver et mémoriser l'adresse de début de la table de symboles Panoramic
function LocalizePanoramicSymbolTable(a: integer):integer; stdcall; export;
{
  Pour tomber sur le début d'une entrée de table de symbole (pointeur vers le nom),
  il faut calculer adr(variable)-delta
  avec delta=12 pour un entier et delta=24 pour un flottant.
  Donc, cette fonction suppose être appelée avec adr(number_click). Cette variable
  est toujours définie et est de type flottant. Ensuite, chaque entrée dans la
  table de synboles a une longueur de 80 ou 4*26 caractères (50 hexa).

  Pour les tableaux, on sait les éléments suivants;
  - dim t%(3)  t% n'est pas dans la table de symbole de base
  - dim t%(3)  adr(t%) pointe vers la liste des éléments t%(0),t%(1),t%(2),t%(3)

  Une entrée dans la table de symboles Panoramic a la structure suivante:
    mot  offset  utilisation
    ----------------------------------------------------------------------------
    0      0    adresse du nom sous forme de chaîne de caractères (majuscules)
    1      4    type de variable (1...9)
    2      8
    3    12    valeur entière si type=1
    4    16
    5    20
    6    24    valeur flottante si type=3 (premier mot)
    7    28    valeur flottante si type=3 (deuxième mot)
    8    32    dimension 1 si type=4 ou type=7: nombre de segments utilisés de ce type + 1
    9    36    dimension 1 si type=5 ou type=8: nombre de segments utilisés de ce type + 1
    10    40    dimension 1 si type=6 ou type=9: nombre de segments utilisés de ce type + 1
    11    44    dimension 1 si type=4: nombre de segments utilisés de ce type + 1
    12    48    dimension 1 si type=8: nombre de segments utilisés de ce type + 1
    13    52    dimension 1 si type=9: nombre de segments utilisés de ce type + 1
    14    56    dimension 1 si type=4 ou type=7
    15    60    dimension 1 si type=5 ou type=8
    16    64    dimension 1 si type=6 ou type=9
    17    68    dimension 2 si type=7
    18    72    dimension 2 si type=8
    19    76    dimension 2 si type=9

  Types:
    1  entier simple
    2  flottant simple
    3  chaîne de caractères simple
    4  tableau d'entiers en une dimension
    5  tableau de flottants en une dimension
    6  tableau de chaînes de caractères en une dimension
    7  tableau d'entiers en deux dimensions
    8  tableau de flottants en deux dimensions
    9  tableau de chaînes de caractères en deux dimensions


}
var
  pi1: pinteger;
begin
  pi1 := pinteger(a-24);
  while pi1^<>0 do pi1 := pinteger(integer(pi1)-4*PanoramicSymbolTableEntrySize);
  pi1 := pinteger(integer(pi1)+4*PanoramicSymbolTableEntrySize);
  PanoramicSymbolTable := pi1;
  result := integer(PanoramicSymbolTable);
{$ifdef debugit}
showmessage('LocalizePanoramicSymbolTable: PanoramicSymbolTable='+inttostr(result)+'  '+inttohex(result,8));
{$endif}
end;
exports LocalizePanoramicSymbolTable;

ou:
Code:
// Cette fonction retourne l'adresse du début de la table des variables de Panoramic.
// Elle doit être appelée avec l'adresse d'une variable système en format flottant,
// comme NUMBER_CLICK par exemple.
function FindSymbolTableStartAddress(a_number_click: pinteger):integer; stdcall; export;
var
  ptr: pinteger;
begin
  result := integer(PanoramicSymbolTable);
  exit;

  result := 0;                // supposer "erreur"
  ptr := a_number_click;
  inc(ptr,-6);                // pointer sur l'adresse du nom de NUMBER_CLICK
  if pstring(ptr)^='NUMBER_CLICK' then begin
    while ptr^<>0 do inc(ptr,-PanoramicSymbolTableEntrySize);
    inc(ptr,PanoramicSymbolTableEntrySize);
    result := integer(ptr);
  end;
end;
exports FindSymbolTableStartAddress;
voir la valeur de PanoramicSymbolTableEntrySize dans les commentaires de la première solution.
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyVen 17 Déc 2021 - 14:58

Voici une petite démo pour lire et écrire des tableaux d'entiers et de flottants. ll suffit de recharger KGF.dll à partir de ma signature et de lancer le code suuivant:
Code:
' test_accès_tableaux.bas

dim res%, entiers%(5), flottants(7), i%

for i%=0 to 5
  entiers%(i%) = i%+100*i%
next i%
for i%=0 to 7
  flottants(i%) = 1/(i%+1)
next i%

dll_on "KGF.dll"

res% = dll_call2("GetIntegerArrayFromPanoramic",adr(entiers%),5)
res% = dll_call2("SetIntegerArrayFromPanoramic",adr(entiers%),5)
for i%=0 to 5
  message "SetIntegerArrayFromPanoramic  "+str$(i%)+": "+str$(entiers%(i%))
next i%

res% = dll_call2("GetFloatArrayFromPanoramic",adr(flottants),7)
res% = dll_call2("SetFloatArrayFromPanoramic",adr(flottants),7)
for i%=0 to 7
  message "SetFlottantArrayFromPanoramic  "+str$(i%)+": "+str$(flottants(i%))
next i%

end


Ce code commence par initialiser un tableau d'entiers et de flottants.
Il appelle ensuite la fonction GetIntegerArrayFromPanoramic qui lit le tableau des entiers de Panoramic et affiche les valeurs reçues.
Puis, il appelle la fonction SetIntegerArrayFromPanoramic qui remplace les éléments du tableau des entiers par d'autres valeurs et affiche ensuite (en Panoramic) les nouvelles valeurs.
Puis, il appelle la fionction GetFloatArrayFromPanoramic qui lit le tableau des flottants de Panoramic et affiche les valeurs reçues.
Puis, il appelle la fonction SetFloatArrayFromPanoramic qui remplace les éléments du tableau des flottants par d'autres valeurs et affiche ensuite (en Panoramic) les nouvelles valeurs.

Voici le code de ces 4 fonctions:
Code:
// copier un tableau de type integer de Panoramic dans un tableau dynamique Delphi dans la DLL
function GetIntegerArrayFromPanoramic(aIntegerArray: pinteger; nDimension: integer): integer; stdcall; export;
var
  IntegerArray: array of Integer;
  i: integer;
  pi: pinteger;
begin
  result := -1;
  try
    if aIntegerArray=nil then exit;            // il faut au moins une adresse
    if nDimension<0 then exit;                 // il faut une dimenion Panoramic valide
    SetLength(IntegerArray,nDimension+1);      // affecter la mémoire
    pi := aIntegerArray;                       // boucle de lecture
    for i:=0 to nDimension do begin
      IntegerArray[i] := pi^;                  // ccpier un élément
      inc(pi);                                 // ajuster le pointeur
showmessage(format('GetIntegerArrayFromPanoramic  %d: %d',[i,IntegerArray[i]]));   // juste pour montrer le résultat - ligne à supprimer !
    end;
    result := 0;
  except
  end;
end;
exports GetIntegerArrayFromPanoramic;

// copier un tableau de type integer d'un tableau dynamique Delphi dans la DLL vers un tableau dans Panoramic
function SetIntegerArrayFromPanoramic(aIntegerArray: pinteger; nDimension: integer): integer; stdcall; export;
var
  IntegerArray: array of Integer;
  i: integer;
  pi: pinteger;
begin
  result := -1;
  try
    if aIntegerArray=nil then exit;                  // il faut au moins une adresse
    if nDimension<0 then exit;                       // il faut une dimenion Panoramic valide

    // les 2 lignes suivantes sont là pour "simuler" un tableau existant dans la DLL...
    SetLength(IntegerArray,nDimension+1);            // affecter la mémoire
    for i:=0 to nDimension do IntegerArray[i] := i*2;

    if nDimension>=Length(IntegerArray) then exit;   // trop de données demandées ?
    pi := aIntegerArray;                             // boucle d'écriture
    for i:=0 to nDimension do begin
      pi^ := IntegerArray[i];                          // ccpier un élément
      inc(pi);                                         // ajuster le pointeur
    end;
    result := 0;
  except
  end;
end;
exports SetIntegerArrayFromPanoramic;

// copier un tableau de type float de Panoramic dans un tableau dynamique Delphi dans la DLL
function GetFloatArrayFromPanoramic(aFloatArray: pfloat; nDimension: integer): integer; stdcall; export;
var
  FloatArray: array of double;
  i: integer;
  pf: pfloat;
begin
  result := -1;
  try
    if aFloatArray=nil then exit;              // il faut au moins une adresse
    if nDimension<0 then exit;                 // il faut une dimenion Panoramic valide
    SetLength(FloatArray,nDimension+1);        // affecter la mémoire
    pf := aFloatArray;                         // boucle de lecture
    for i:=0 to nDimension do begin
      FloatArray[i] := pf^;                      // ccpier un élément
      inc(pf);                                   // ajuster le pointeur
showmessage(format('GetFloatArrayFromPanoramic  %d: %f',[i,FloatArray[i]]));   // juste pour montrer le résultat - ligne à supprimer !
    end;
    result := 0;
  except
  end;
end;
exports GetFloatArrayFromPanoramic;

// copier un tableau de type float d'un tableau dynamique Delphi dans la DLL vers un tableau dans Panoramic
function SetFloatArrayFromPanoramic(aFloatArray: pfloat; nDimension: integer): integer; stdcall; export;
var
  FloatArray: array of double;
  i: integer;
  pf: pfloat;
begin
  result := -1;
  try
    if aFloatArray=nil then exit;                    // il faut au moins une adresse
    if nDimension<0 then exit;                       // il faut une dimenion Panoramic valide

    // les 2 lignes suivantes sont là pour "simuler" un tableau existant dans la DLL...
    SetLength(FloatArray,nDimension+1);              // affecter la mémoire
    for i:=0 to nDimension do FloatArray[i] := i*2.002;

    if nDimension>=Length(FloatArray) then exit;     // trop de données demandées ?
    pf := aFloatArray;                               // boucle de lecture
    for i:=0 to nDimension do begin
      pf^ := FloatArray[i];                            // ccpier un élément
      inc(pf);                                         // ajuster le pointeur
    end;
    result := 0;
  except
  end;
end;
exports SetFloatArrayFromPanoramic;

Voila pour le "prrof of concept". Je n'ai pas fait une nouvelle version de KGF.dll. Ces fonctions étaient présentes mais non exportées et non documentées. Je les ai simplement exportées.
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
jean_debord

jean_debord


Nombre de messages : 1250
Age : 69
Localisation : Limoges
Date d'inscription : 21/09/2008

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptySam 18 Déc 2021 - 11:12

Merci encore pour ces exemples, Klaus Smile

C'est bien ce que j'avais prévu de faire en FreeBASIC.

Mais j'ai besoin des tableaux à 2 dimensions (matrices) pour mes applications. Donc il faut que je trouve une astuce.

Le plus simple serait de passer tout le tableau dans une chaîne de caractères. par exemple :

"{1,2,3,4}"

"{{1,2,3,4}, {5,6,7,8}}"

Il suffirait de se mettre d'accord sur la syntaxe (ici j'ai repris celle de FreeBASIC)
Revenir en haut Aller en bas
http://www.unilim.fr/pages_perso/jean.debord/index.htm
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptySam 18 Déc 2021 - 11:41

Ouais... c'est imaginable en "entrée", en tant que valeur constante. C'est impossible en "sortie", et c'est impossible en entrée en tant que variable existant de façon permmanente dans le programme appelant.

Je ne connais pas l'implémentation des tableaux multi-dimensionnels en FreeBasic. En ce qui concerne Panoramic, le passage de ce genre de tableaux est impossible, tant entrée qu'en sortie.

Mais tu peux essayer autre chose. Par définition, le canvas d'une image est une matrice à deux dimensions, et si tu crées la bitmap en format 32 bits, tu as un tableau en deux dimensions de valeurs de type integer. Il suffira alors de passer le handle du canvas pour y avoir accès. Là encore, pas question de mémoriser ce handle d'un appel d'une fonction DLL à unn autre - le handle du canvas peut changer après chaue opération modifiant le canvas.

Autre possibilité: utiliser un objet LIST caché (je parle toujours pour le couple Panoramic/Delphi que je connais bien) et dont le handle ne varie jamais pendant la durée de vie de l'objet. Tu peux imaginer de lacer dans chaque ligne de l'objet une suite de données déparées par des virgules simulant ainsi la deuxième dimension. Dans la DLL, tu récupères une ligne quelconque selon le premier indice, tu la charge dans un objet TStringList temporaire (Delphi...) et tu utilises le second indice pour trouver l'élément choisi dans cette liste. Idem pour le retour d'information - il suffira de remplacer els données de l'objet LIST initial via le handle passé en paramètre. Tu as ainsi une olution bi-directionnelle pour une simulation de tableaux en deux dimensions.
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
papydall

papydall


Nombre de messages : 7002
Age : 73
Localisation : Moknine (Tunisie) Entre la chaise et le clavier
Date d'inscription : 03/03/2012

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptySam 18 Déc 2021 - 13:45

Bonjour tout le monde
@Klaus et Jean_debord.
Suggestion :
Il est toujours possible de simuler un tableau à deux dimensions ou plus en un tableau à une seule dimension.

Exemple
dim x,y
x = 10 : y = 7
dim tab2(x,y)
peut être simulé par
dim tab1(x*y)

Pour accéder au contenu de tab2(3,5) par exemple, on fait
valeur = tab2(3,5)

Pour le tableau à une seule dimension tab1() ça sera
valeur = tab1(3*x+5).

J'ai traité la simulation d'un tableau à 3 dimensions en un tableau à 2 dimensions sur ce post

C'est peut-être une idée à approfondir.  Question
Revenir en haut Aller en bas
http://papydall-panoramic.forumarabia.com/
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptySam 18 Déc 2021 - 14:09

Très bien, ton idée, Papydall ! Surtout parce qu'on peut déclarer uen fonction du même nom que le tableau à 2 dimensions à laquelle on passe les deux indices et qui fait le calcul àn l'intérieur? Idem avec une SUB pour l'écriture dans le tableau.

Ainsi, par extension, on peut traiter un tableau de n'importe quelle dimension par un tableau physique d'une seule dimension, et ce en Panioramic pur. Du coup, le probème de passage de tableaux multi-dimensions à une DLL est résolu...
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
papydall

papydall


Nombre de messages : 7002
Age : 73
Localisation : Moknine (Tunisie) Entre la chaise et le clavier
Date d'inscription : 03/03/2012

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptySam 18 Déc 2021 - 15:08

Ich freue mich sehr, dass ich dabei geholfen habe, ein kleines Problem zu lösen! Basketball Basketball Basketball
Revenir en haut Aller en bas
http://papydall-panoramic.forumarabia.com/
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptySam 18 Déc 2021 - 15:43

Nicht nur geholfen - ich glaube, das ist DIE Lösung !
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptySam 18 Déc 2021 - 18:38

Selon la suggestion de Papydall, j'ai fait une petite démo montrant comment on peut gérer un tableau d'entiers de 6 lignes sur 4 colonnes, dans un tableau uni-dimensionnel. Ce tableau peut alors facilement être passé à une fonction d'une DLL:
Code:
' Tableau_en_2_dimensions_avec_Panoramic_et_DLL.bas

dim res%, i%, j%, s$

' dim entiers%(5,3)
dim entiers%(6*4-1)     : ' les longueurs des dimensions sont 6 x 4 cases !

for i%=0 to 5
  for j%=0 to 3
    entiers(i%*100+j%,i%,j%)
  next j%
next i%

for i%=0 to 5
  s$ = ""
  for j%=0 to 3
    s$ = s$ + str$(fentiers%(i%,j%)) + "   "
  next j%
  print s$
next i%


end

' *** lire l'élément (i%,j%) du tableau entiers%
' ATTENTION: la fonction ne peut PAS avoir le même nom que le tableau !
'            Son nom est donc précédé d'un "f" pour signaler "fonction"
fnc fentiers%(i%,j%)
  result entiers%(i%*4+j%)     : ' la première dimension a une longueur de 6 !
end_fnc

' *** écrire la valeur v% dans l'élémént (i%,j%) du tableau entiers%
sub entiers(v%,i%,j%)
  entiers%(i%*4+j%) = v%
end_sub


Dernière édition par Klaus le Lun 20 Déc 2021 - 12:22, édité 1 fois
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Klaus

Klaus


Nombre de messages : 12289
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyDim 19 Déc 2021 - 7:49

J'ai créé un objet MDA (Multi-DimensionalArray) permettant de gérer des tableaux Panoramic en 2 ou 3 dimensions à condition que ces tableaux soient simulés dans un tableau uni-dimensionnel. Il 'agit d'un objet interne à une DLL en Delphi (ou implémentation similaire dans d'autres langages). Deux fonctions exportées permettent de déclarer les tableaux multi-dimensionnels simulés, l'autre permet d'effacer toutes les déclarations. Puis, non accessibles par Panoramic mais utilisables à l'intérieur de la DLL, des fonctions et procédures permettant d'accéder ces tableaux directement à partir de la DLL sans avoir à les recopier. La condition incontournable est que l'adresse du talbleau uni-dimensionnel soit passée à la fonction DLL appelée par Panoramic.

Voici le code de l'objet en Delphi:
Code:
{
  Objet MDA - Multi-DimensionalArray

  Cet objet permet de gérer des tableaux multi-dimensionnels simulés dans un tableau Panoramic uni-dimensionnel.
  L'intérêt de ce système est que les tableaux uni-dimensionnels peuvent facilement être passés en paramètre à la DLL.
  Ce n'est pas le cas des tableaux uni-dimensionnels.
  L'objet MDA est conçu pour donner accès aux fonctions d'une DLL aux données d'un tableau multi-dimensionnel de Panoramic.
  Pour cela, il faut déclarer en Panoramic un tableau uni-dimensionnel selon la formule:
        dim MonTableau((dim1+1) * (dim2+1) * (dim3+1) - 1)
  Exemple:
    dim MonTableau(5,3,7)
  sera remplacé par
    dim MonTableau(6*4*8-1)

  L'implémentation actuelle est prévue pour des tableaux jusqu'à 3 dimensions.

  Un tableau multi-dimensionnel doit être déclaré avec son nom et ses dimenions.
  L'objet MDA mémorise et gère toutes les déclarations ainsi que l'accès physique aux données.
  Deux fonctions exportées (accessibles en Panoramic) permettent définir les tableaux:
      res% = dll_call4("DefineMDA",adt(tableau$),d1%,d2%,d3%)    : ' crée ou modifie la déclaration d'un tableau
      res% = dll_call0("ResetMDA")                                : ' efface toutes les déclarations de tableaux
  Les fonctions et procédures suivantes sont utilisables dans la DLL (en Delphi), mais pas appelables par Panoramic:
      MDA.IndexOfArray(aName: string): string                    retourne l'index du tableau ou -1 si non déclaré
      MDA.TypeOfArray(aName: string): TypMDA                      retourne le type d'un tableau
      MDA.GetIntegerArrayElement(aIndex, d1,d2,d3: integer; aPanoramic: pinteger): integer    retourne le contenu d'un élément
      MDA.GetFloatArrayElement(aIndex, d1,d2,d3: integer; aPanoramic: pfloat): double          retourne le contenu d'un élément
      MDA.SetIntegerArrayElement(aIndex, d1,d2,d3: integer; aValue: integer; aPanoramic: pinteger)      remplace le contenu d'un élément
      MDA.SetFloatArrayElement(aIndex, d1,d2,d3: integer; aValue: double; aPanoramic: pfloat)          remplace le contenu d'un élément
}
type TypMDA = (tMDAundefined, tMDAfloat, tMDAinteger, tMDAstring);
type TMDA = class
  private
    fNames: array of string;
    fTypes: array of TypMDA;
    fDimensions: array of array of integer;
  published
    function IndexOfArray(aName: string): integer;
    function TypeOfArray(aName: string): TypMDA;
    function GetIntegerArrayElement(aIndex, d1,d2,d3: integer; aPanoramic: pinteger): integer;
    function GetFloatArrayElement(aIndex, d1,d2,d3: integer; aPanoramic: pfloat): double;
    procedure SetIntegerArrayElement(aIndex, d1,d2,d3: integer; aValue: integer; aPanoramic: pinteger);
    procedure SetFloatArrayElement(aIndex, d1,d2,d3: integer; aValue: double; aPanoramic: pfloat);
    procedure AddArray(aName: string; d1, d2, d3: integer);
    procedure ModifyArray(aName: string; d1, d2, d3: integer);
    constructor CreateNew;
    destructor Destroy;
end;

var
  MDA: TMDA;

Implementation

constructor TMDA.CreateNew;
begin
  inherited;
  SetLength(fNames,0);
  SetLength(fTypes,0);
  SetLength(fDimensions,0);
end;

destructor TMDA.Destroy;
begin
  SetLength(fNames,0);
  SetLength(fTypes,0);
  SetLength(fDimensions,0);
  inherited;
end;

function TMDA.IndexOfArray(aName: string): integer;
var
  i: integer;
begin
  result := -1;
  if Length(fNames)=0 then exit;
  for i:=0 to high(fNames) do begin
    if fNames[i]=aName then begin
      result := i;
      exit;
    end;
  end;
end;

function TMDA.TypeOfArray(aName: string): TypMDA;
var
  i: integer;
begin
  result := tMDAundefined;
  i := IndexOfArray(aName);
  if i>=0 then result := fTypes[i];
end;

function TMDA.GetIntegerArrayElement(aIndex, d1,d2,d3: integer; aPanoramic: pinteger): integer;
var
  pi: pinteger;
  offset: integer;
begin
  result := 0;
  if (aIndex<0) or (aIndex>high(fNames)) then exit;
  pi := aPanoramic;
  offset := d1*fDimensions[aIndex][1] + d2*fDimensions[aIndex][2] + d3;
  inc(pi,offset);
  result := pi^;
end;

function TMDA.GetFloatArrayElement(aIndex, d1,d2,d3: integer; aPanoramic: pfloat): double;
var
  pf: pfloat;
  offset: integer;
begin
  result := 0;
  if (aIndex<0) or (aIndex>high(fNames)) then exit;
  pf := aPanoramic;
  offset := d1*fDimensions[aIndex][1] + d2*fDimensions[aIndex][2] + d3;
  inc(pf,offset);
  result := pf^;
end;



procedure TMDA.SetIntegerArrayElement(aIndex, d1,d2,d3: integer; aValue: integer; aPanoramic: pinteger);
var
  pi: pinteger;
  offset: integer;
begin
  if (aIndex<0) or (aIndex>high(fNames)) then exit;
  pi := aPanoramic;
  offset := d1*fDimensions[aIndex][1] + d2*fDimensions[aIndex][2] + d3;
  inc(pi,offset);
  pi^ := aValue;
end;

procedure TMDA.SetFloatArrayElement(aIndex, d1,d2,d3: integer; aValue: double; aPanoramic: pfloat);
var
  pf: pfloat;
  offset: integer;
begin
  if (aIndex<0) or (aIndex>high(fNames)) then exit;
  pf := aPanoramic;
  offset := d1*fDimensions[aIndex][1] + d2*fDimensions[aIndex][2] + d3;
  inc(pf,offset);
  pf^ := aValue;
end;


procedure TMDA.AddArray(aName: string; d1, d2, d3: integer);
var
  i: integer;
begin
  i := Length(fNames);
  SetLength(fNames,i+1);
  SetLength(fTypes,i+1);
  SetLength(fDimensions,i+1);
  SetLength(fDimensions[i],3);
  fNames[i] := aName;
  fTypes[i] := tMDAfloat;
  if RightStr(aName,1)='%' then fTypes[i] := tMDAinteger;
  if RightStr(aName,1)='$' then fTypes[i] := tMDAstring;
  fDimensions[i][0] := d1;
  fDimensions[i][1] := d2;
  fDimensions[i][2] := d3;
end;

procedure TMDA.ModifyArray(aName: string; d1, d2, d3: integer);
var
  i: integer;
begin
  i := self.IndexOfArray(aName);
  fNames[i] := aName;
  fTypes[i] := tMDAfloat;
  if RightStr(aName,1)='%' then fTypes[i] := tMDAinteger;
  if RightStr(aName,1)='$' then fTypes[i] := tMDAstring;
  fDimensions[i][0] := d1;
  fDimensions[i][1] := d2;
  fDimensions[i][2] := d3;
end;


Et les fonctions exportées:
Code:
// cette fonction ajoute ou modifie la déclaration d'un tableau
function DefineMBA(aName: integer; d1, d2, d3: integer): integer; stdcall; export;
var
  s: string;
  index: integer;
begin
  result := -1;
  try
    if not assigned(MDA) then MDA := TMDA.CreateNew;                            // créer la table maître si besoin
    s := Trim(GetStringFromPanoramic(aName));                                  // prendre le nom Panoramic du tableau
    if s='' then exit;                                                          // nom manquant ?
    index := MDA.IndexOfArray(s);                                              // chercher le tableau dans la table maître
    if index<0 then begin                                                      // tableau pas encore enregistré ?
      MDA.AddArray(s,d1,d2,d2);                                                //  ajouter une nouvelle déclaration
    end else begin                                                              // tableau déjà enregistré - changer dimensions
      MDA.ModifyArray(s,d1,d2,d3);                                              //  modifier la définition du tableau
    end;
    result := 0;
  except
  end;
end;
exports DefineMBA;

// cette fonctiob efface toutes les déclarations de tableaux (PAS LES TABLEAUX !)
function ResetMDA: integer; stdcall; export;
begin
  result := -1;
  try
    if not assigned(MDA) then exit;
    MDA.Free;
    result := 0;
  except
  end;
end;
exports ResetMDA;

Ainsi, une fonction DLL peut recevoir l'adresse du tableau simulé et éventuellement des indices en paramètre, puis travailler directement surb les données, en lécture et en mise à jour. Il faut juste passer chaque foir l'adresse de ce tableau simulée et non une valeur stockée dans une variable, l'adresse pouvant changer dynamiquement (pendant l'exécution du code Panoramic, pas pendant l'exécution de la fonction DLL !).
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
papydall

papydall


Nombre de messages : 7002
Age : 73
Localisation : Moknine (Tunisie) Entre la chaise et le clavier
Date d'inscription : 03/03/2012

Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? EmptyDim 19 Déc 2021 - 8:11

Belle avancée, merci Klaus !
« La persévérance et le travail finissent toujours par payer ! »
Revenir en haut Aller en bas
http://papydall-panoramic.forumarabia.com/
Contenu sponsorisé





Des DLL pour Panoramic ? Empty
MessageSujet: Re: Des DLL pour Panoramic ?   Des DLL pour Panoramic ? Empty

Revenir en haut Aller en bas
 
Des DLL pour Panoramic ?
Revenir en haut 
Page 1 sur 2Aller à la page : 1, 2  Suivant
 Sujets similaires
-
» Aide-mémoire des mots-clés Panoramic
» Logithèque : une base de données en Panoramic pour Panoramic
» Des DLL pour Panoramic
» POUR PANORAMIC
» pour panoramic

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
FORUM DE DISCUSSION SUR LE LANGAGE PANORAMIC :: Expériences autour de PANORAMIC :: Crocodile Basic-
Sauter vers: