[..] Creation structure en cascade avec pointeur

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Répondre
duke164
Niveau 1
Niveau 1
Messages : 6
Enregistré le : lun. 17 janv. 2011 21:52
Status : Hors ligne

[..] Creation structure en cascade avec pointeur

#1

Message par duke164 »

Bonjour,

Je me suis intéressé à la puissance d'Autoit car j'ai un projet pour tenter d'automatiser un couteau

suisse du traitement d'image pour l'astro (IRIS)
J'avais commencé par tenter l'écriture semi automtique de script IRIS. Puis j'ai découvert Autoit.
Dans mon projet j'ai besoin d'accéder à une DLL qui contient toute une bibliothèque spécialisee.
Après avoir testé l'appel de cette dll au trvers de fonction simple je me suis attaqué à l'appel de

fonction dont j'ai besoin mais qui font appel aux structure. Et là je suis coincé. Je n'ai pas trouvé

la solution ni ce forum ni dans son homologue américain.

Mon problème concerne l'appel d'une fonction dont une des variables est un pointeur vers une structure
complexe à étage.La fonction de base est :

Code : Tout sélectionner

int ffopen(fitsfile **fptr, const char *filename, int iomode, int *status)
que j'ai traduite en autoit par

Code : Tout sélectionner

$return = DllCall("cfitsio.dll", "int:cdecl", "ffopen", "ptr",DllStructGetPtr($fitsfile),"str","name.fit","int",0,"int",$status)
avec toutes les déclarations qui vont bien.

Le problème se situe au niveau de la structure construite ainsi :

Code : Tout sélectionner

typedef struct        /* structure used to store table column information */
{
    char ttype[70];   /* column name = FITS TTYPEn keyword; */
...
    long  twidth;     /* width of each ASCII table column */
}tcolumn;

typedef struct      /* structure used to store basic FITS file information */
{
    int filehandle;   /* handle returned by the file open function */
....
    tcolumn *tableptr;   /* pointer to the table structure */
...
    void *tiledata;         /* uncompressed tile of data, for row tilerow */
    char *tilenullarray;    /* optional array of null value flags */
    char *iobuffer;         /* pointer to FITS file I/O buffers */
 ....
    int ageindex[NIOBUF];  /* relative age of each buffer */  

} FITSfil;
typedef struct         /* structure used to store basic HDU information */
{
    int HDUposition;  /* HDU position in file; 0 = first HDU */
    FITSfil *Fptr;   /* pointer to FITS file structure */
}fitsfile;
Et là je séche sur la façon de la construire. En fait j'ai trouvé des infos sur les sous structure mais

ne faisant pas référence à des pointeurs de structure. Aussi je ne vois pas comment m'en sortir si cela

est même possible. Je ne sais pas programmé en C même si je peux un peu le comprendre.

Pouvez-vous m'aider ? Merci.
Avatar du membre
Tlem
Site Admin
Site Admin
Messages : 11824
Enregistré le : ven. 20 juil. 2007 21:00
Localisation : Bordeaux
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#2

Message par Tlem »

Houlaaaa, ça c'est de la question ... :lol:
Thierry

Rechercher sur le forum ----- Les règles du forum
Le "ça ne marche pas" est une conséquence commune découlant de beaucoup trop de raisons potentielles ...

Une idée ne peut pas appartenir à quelqu'un. (Albert Jacquard) tiré du documentaire "Copié n'est pas volé".
Avatar du membre
poke123
Niveau 2
Niveau 2
Messages : 26
Enregistré le : mer. 24 mars 2010 14:22
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#3

Message par poke123 »

j'ai déjà tenter de faire des structures à étage mais autant dire que c'est mort avec autoit par contre, il devrait être possible de faire la structure byte par byte à la main puis de le passer en structure de byte (à tester sur un truc plus simple) ou sinon y a t'il moyen de lui passer le binaire en dur et qu'il refasse sa structure avec ?
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#4

Message par jchd »

C est un langage typé donc un tcolumn * n'est pas un pointeur tout bête, mais un pointeur sur une structure de type tcolumn.
AutoIt en revanche est bien plus permissif et te permet de confondre un tcolumn * avec un bête void * un pointeur sur quelque chose.
Tu vas donc devoir faire :
;; /* structure used to store table column information */
$tcolumn = DllStructCreate('char ttype[70]; ... ; long twidth')

;; /* structure used to store basic FITS file information */
Global Const NIOBUF = 1024 ; au hasard
$FITSfil = DllStructCreate('int filehandle; ... ; ptr tableptr; ... ; ptr tiledata; char *tilenullarray; char *iobuffer; ... ; int ageindex[NIOBUF]')

;; /* structure used to store basic HDU information */
$fitsfile = DllStructCreate('int HDUposition; ptr Fptr')

J'ai laissé les tags (noms des champs des structures) pour la clarté, mais ils ne jouent aucun autre rôle.
Pour créer une "vraie" structure $fitsfile utilisable, il te faut initialiser les pointeurs.
DllStructSetData($fitsfile, 2, DllStructGetPtr($FITSfil)) ; initialise Fptr
DllStructSetData($FITSfil, 5 <je mets une valeur au pif, il y a des ... dans la structure>, DllStructGetPtr($tcolumn)) ; initialise tableptr

Non testé mais sauf typo, cela doit fonctionner sans souci.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
duke164
Niveau 1
Niveau 1
Messages : 6
Enregistré le : lun. 17 janv. 2011 21:52
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#5

Message par duke164 »

Merci pour ces 1ere réponses. Malgré tout mais je m'en doutais ca plante encore dans la dll (les structures sont complexes)
Question : ne faut-il pas dans l'ordre créer :

Code : Tout sélectionner

$tcolumn = dllstructcreate("char ttype[70]; int64 tbcol;int  tdatatype; int64 trepeat;double tscale; double tzero;int64 tnull; char strnull[20];char tform[10]; long  twidth;")
créer :

Code : Tout sélectionner

$FITSfile = dllstructcreate("int filehandle; int driver;int open_count;char _filename;int validcode;int only_one;int64 filesize;int64 logfilesize;int lasthdu;int64 bytepos;int64 io_pos;int curbuf;int curhdu;int hdutype;int writemode;int maxhdu;int MAXHDUb;int64 _headstart;int64 headend;int64 ENDpos;int64 nextkey;int64 datastart; int imgdim;int64 imgnaxis[99];int tfield;int64 origrows;int64 numrows;int64 rowlength;ptr _tableptr; int64 heapstart;int64 heapsize;int request_compress_type;long request_tilesize[6]; float request_hcomp_scale;int request_hcomp_smooth;int request_quantize_dither ; int compressimg;int quantize_dither;char zcmptype[12];int compress_type;int zbitpix;int zndim;long znaxis[6];long tilesize[6];long maxtilelen;long maxelem;int cn_compressed;int cn_uncompressed;int cn_zscale;int cn_zscale;int cn_zzero;int cn_zblank;double zscale;double zzero;double cn_bscale;double cn_bzero;double cn_actual_bzero;int zblank;int rice_blocksize;int rice_bytepix;float quantize_level;float hcomp_scale;int hcomp_smooth;int  tilerow;long tiledatasize;int tiletype;ptr _tiledata;char _tilenullarray;int tileanynull;char _iobuffer;long bufrecnum[40];int dirty[40];int ageindex[40]")
initialiser la donnée _tableptr

Code : Tout sélectionner

DllStructSetData($FITSfile, "_tableptr" , DllStructGetPtr($tcolumn)) ; initialise tableptr
créer :

Code : Tout sélectionner

    $fitsfil = dllstructcreate("int HDUposition;ptr _FITSfile;")
initialiser la donnée _FITSfile

Code : Tout sélectionner

DllStructSetData($fitsfil, "_FITSfile", DllStructGetPtr($FITSfile)) ; initialise _FITSfile
Avant d'appeler la fonction :

Code : Tout sélectionner

    $return = DllCall("cfitsio.dll", "int:cdecl", "ffopen", "ptr", DllStructGetPtr($fitsfil),"str","irc1.fit","int",0,"int",$status)
En quoi l'initialisation telle quel aide à construire la structure en lui réservant l'espace mémoire qui va bien. Pour moi c'était DllStructCreate qui faisait ca.
Avatar du membre
cutprod
Niveau 6
Niveau 6
Messages : 273
Enregistré le : jeu. 30 sept. 2010 17:25
Localisation : Sud Ouest
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#6

Message par cutprod »

Bonjour, excuser moi de m' imisser dans le post :? , mais je vois qu'il y'a des spécialistes es "structures' :lol:
Peut être pourriez vous m'aider? = http://autoitscript.fr/forum/viewtopic.php?f=3&t=6669
Juste un problème de syntaxe pour récupèrer des infos dans une structure en tableau.
Je sais c'est mal ça se fais pas de profiter du post d'un copain... Mais y'a pas grand monde qui m'aide et qu'est ce quelle a de plus que la mienne sa structure :lol: :lol: (a part qu'elle est 10* plus complexe :lol: )
Je :arrow:
Cut, srcipteur du dimanche...désolé !-)
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#7

Message par jchd »

@poke123, je ne vois pas pourquoi "c'est mort avec AutoIt". Une justification ?

@duke164, Oui, c'est bien le principe. DllStructCreate réserve en effet la mémoire pour la structure et renvoie une variable de type Struct.
Dans ton cas, l'initialisation est requise sinon un pointeur vers une sous-structure resterait à zéro. Il en va de même en C, la seule vraie distinction étant que C offre un typage des structures alors qu'AutoIt ne sait qu'instancier à chaque fois par DllStructCreate muni du paramètre de description de la structure.

Pour la clarté, quand une chaîne de description de structure est complexe, on a fort intérêt à la décomposer par ligne :

Code : Tout sélectionner

$tcolumn = dllstructcreate( _
  "char   ttype[70];" & _
  "int64  tbcol;" & _
  "int    tdatatype;" & _
  "int64  trepeat;" & _
  "double tscale;" & _
  "double tzero;" & _
  "int64  tnull;" & _
  "char   strnull[20];" & _
  "char   tform[10];" & _
  "long   twidth;" _
)
Maintenant, pourquoi ton bidule plante ne me saute pas aux yeux. La convention d'appel est-elle bien cdecl ? L'alignement est-il bon ? Tous les paramètres sont-ils bien initialisés à des valeurs correctes ? Attention entre x86 et x64 pour la taille 32 ou 64 bits !
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
duke164
Niveau 1
Niveau 1
Messages : 6
Enregistré le : lun. 17 janv. 2011 21:52
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#8

Message par duke164 »

Merci jchd !
Je vais essayer le debugger WinDbg pour tenter de comprendre s'il y des problèmes d'offset (alignement) bien que je ne maitrise rien sur le sujet mais j'en comprend le principe.
Pour le x86 ou x64 j'avais vu qcq dans l'aide où il fallait prendre en compte cet aspect mais je ne le retrouve pas.
En quoi est-ce important ?
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#9

Message par jchd »

La taille des pointeurs double, ce qui n'est pas rien (ça plante si ptr en 32 au lieu de 64 ou ça décale la suite si vice-versa).
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
duke164
Niveau 1
Niveau 1
Messages : 6
Enregistré le : lun. 17 janv. 2011 21:52
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#10

Message par duke164 »

Bien là je ne plante plus mais c'est un peu le hasard car j'ai fait qcq que je ne comprends pas bien.
En effet j'ai testé des fonctions simples de la dll comme celle là

Code : Tout sélectionner

ffvers ( > float *version)
que j'ai traduis en

Code : Tout sélectionner

$return = dllCall("cfitsio.dll", "float:cdecl", "ffvers", "float*", $version)
Ne connaissant pas le C j'ai d'abord essayé sans mettre * derriere le float et la ca plantait. Quand le l'ai mis comme ci-dessus ca marche.
Par contre quand je regarde la valeur de $version la variable est vide. Est-ce normal ?
Et si j'affiche la variable return[0] ou return[1] là j'ai qcq de cohérent.

Du coup j'ai fait la même chose pour pour la fonction ffopen (voir ci-dessus) et là ca ne plante plus.

Code : Tout sélectionner

int ffopen (fitsfile **fptr, char *filename, int iomode, > int *status)
traduit en

Code : Tout sélectionner

$return = DllCall("cfitsio.dll", "int:cdecl", "ffopen", "ptr", DllStructGetPtr($fitsfil),"str*","irc1.fit","int",0,"int*",$status)
Bon ca ne veut pas dire que ca marche mais c'est déjà un progrés.
Bon par contre je ne comprends pas ce que j'ai fait. J'ai bien lu dans l'aide que rajouté l'* au type permettait passer un type par référence qui n'est pas l'intial. Mais si qn peut m'expliquer.

Sinon je continue à tester pour voir si ca marche reellement.
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#11

Message par jchd »

Moi non plus je ne capte pas tout. Si ffvers est une fonction qui renvoie un numéro de version, pourquoi passer un pointeur sur un float en entrée et quoi mettre dans le float ?

Autant je comprends une définition comme ça :
float ffvers(void);

Je récupère le numéro de version (du hardware ou du firmware) en appelant la fonction, autant je vois mal ça :
float ffvers(float *aquoijesers);

Ou alors la description avec ffvers ( > float *version) signifie autre chose, mais ce n'est pas du C.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
duke164
Niveau 1
Niveau 1
Messages : 6
Enregistré le : lun. 17 janv. 2011 21:52
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#12

Message par duke164 »

Pour le signe > l'explication est celle là
"A right arrow symbol (>) is used in the function descriptions to separate the input parameters
from the output parameters in the definition of each routine. This symbol is not actually part of
the C calling sequence"
Ce n'est pas du C d'ailleurs le code source récupéré donne çà pour l'entete de la fonction

Code : Tout sélectionner

float ffvers(float *version)  /* IO - version number */
Mis à part ca la bibliothèque utilise énormément de pointeurs pour passer les arguments.

Bon par contre: ok j'ai compris que si je passais le bon type d'argument ici un pointeur et non un float la fonction marche mais quel est la différence entre un void et une * en C ?
De plus dans la fonction que je cherche à utiliser notamment le ffopen objet de mon fil il font appel à **ftpr là ou j'utilise moi un DllStructGetPtr($fitsfil). Que signifie la double ** ?
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#13

Message par jchd »

En C tagada * signifie un pointeur sur un tagada.
Un void * est un pointeur sur quelque chose (ce qui empêche le compilateur de faire certaines vérifications comme type, alignement).
En C on peut "caster" c'est à dire faire accepter au compilo qu'un void * est en fait un tagada* avec la syntaxe (tagada *) devant l'identificateur.

Avec AutoIt, qui au niveau des structures ne connaît pas les types composés (genre structure), un ptr = void * va très bien signifier un pointeur sur n'importe quoi. C'est à toi de ne pas te mélanger les crayons.

* peut être appliqué à un pointeur et la chose devient un pointeur sur un pointeur sur quelque chose.

Dans ton cas de ffopen, ton **fptr est un ptr* pour AutoIt et tu dois probablement l'initialiser avec un pointeur sur un élément de structure qui pointe sur ta structure complexe. Dans ce cas il te faut une structure intermédiaire avec juste un ptr dedans.

Par ailleurs, va pour l'explication du fait que la version soit un paramètre d'entrée et une valeur de retour, mais c'est zarbi pour le moins.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
duke164
Niveau 1
Niveau 1
Messages : 6
Enregistré le : lun. 17 janv. 2011 21:52
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#14

Message par duke164 »

J'ai pas pu bosser beaucoup sur mes problème de structures mais ca y est ca marche en partie.
En fait je n'ai pas besoin de créer ma structure car le progarmme fonctionne surtout avec des pointeurs.
Donc le problème c'était qu'effectivement le bon argument pour ouvrir un fichier et créer la structure devait être un pointeur de structure mais passé en référence.
Après ca j'ai créé des structures sur la base du pointeur retourné par la fonction d'ouverture de fichier et en cascade créer les structures sur la base des pointeurs lus dans les différentes structures et ca marche. Par exemple

Code : Tout sélectionner

$return = DllCall("cfitsio.dll", "int:cdecl", "ffopen", "ptr*", $starfptr, _
        "str", "demom57.fit", "int", 1, "int*", $status)
MsgBox(262144, "ffopen retour fonction (status)", $return[0])
MsgBox(262144, "ffopen pointeur structure", $return[1])
$fptr = DllStructCreate(    "int    HDUposition;" & _
                            "ptr    _FITSfile;",$return[1])
MsgBox(262144, "DllStruct fptr", "Struct Size: " & DllStructGetSize($fptr) & @CRLF & _
        "Struct pointer: " & DllStructGetPtr($fptr) & @CRLF & _
        "Data:" & @CRLF & _
        DllStructGetData($fptr, 1) & @CRLF & _
        DllStructGetData($fptr, 2))
Et j'ai continué avec la grosse structure complexe FITSfile et ca marche.
Mon seul problème reste que la manipulation des fichiers fonctionne avec l'appel des fonctions de la bibliothèque mais que la fonction de fermeture de fichier ne fonctionne pas et que donc je ne peux pas sauver mes modifications de fichier (ie de structure)
Merci quand même pour votre aide surtout jchd.
Salutations
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2284
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Creation structure en cascade avec pointeur

#15

Message par jchd »

N'ayant clairement pas accès à un contexte de test aussi spécifique, j'aurai certainement du mal à aller plus loin. Vérifie N fois le type des paramètres de la ou des fonctions récalcitrantes, car sauf si la fermeture/sauvegarde est "protégée" par un moyen quelconque (sauf paiement d'une licence par exemple) il n'y a pas de raison que ça ne fonctionne pas de façon comparable au reste.

Tu sais où est la sonnette si tu as d'autres questions. Je ne suis pas "vissé" ici, plutôt un visiteur occasionnel, mais tu peux toujours MP-er.

Bonne chance !
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Répondre