Structures en Rebol
ldci8-Jan-2009/22:35:18+1:00
Rebol est un formidable langage que j'adore utiliser pour toutes mes activités. Cependant il me "prend la tête" quelque fois!
exemples
>> a: make struct! [val[integer!]] none
>> a/val: 1
== 1
>> probe type? a/val
integer!

OK: c'est correct

>> a: make struct! [val[decimal!]] none
>> a/val: 1.0
== 1.0
>> probe type? a/val
decimal!

OK : correct et logique

Maintenant

>> a: make struct! [val[binary!]] none
>> a/val: #{312E30} ; to-binary 1.0
>> probe type? a/val
string!

Qui peut m'expliquer pourquoi Rebol revoie une chaîne comme type?
Merci d'avance
DocKimbel9-Jan-2009/7:14:20+1:00
Binary! n'est pas un type accepté par struct!.

La liste des types supportée est décrite ici : http://www.rebol.com/docs/library.html#section-4.2
DocKimbel9-Jan-2009/7:16:10+1:00
La liste des types supporté[s]...
ldci9-Jan-2009/9:30:44+1:00
Merci pour l'info, mais c'est bien dommage car cela m'aurait rendu service pour passer des valeurs Float64 en double précision à une dll.
Bon personne n'est parfait!
DocKimbel9-Jan-2009/21:29:09+1:00
Ton passage de valeur n'est pas bon. En effet, TO-BINARY implique un FORM sur la valeur décimale 1.0 et non une conversion en Float64.

>> as-string to-binary 1.0
== "1.0"

Pour ce que tu veux réaliser, il faudrait procéder plutôt comme celà:

>> a: make struct! [val [double]] none
>> a/val: 1.0
== 1.0
>> third a
== #{000000000000F03F} ; <== représentation de 1.0 en flottant double précision (little endian)

Tu n'as plus qu'à ensuite passer le struct! en argument à la fonction routine! définie pour ta DLL.
ldci9-Jan-2009/23:36:01+1:00
Merci DocKimbel
Je vais regarder en détail ce point durant le week end
ldci10-Jan-2009/1:09:55+1:00
Bon Doc

je n'obtiens pas ce que je veux

Voici en C l'appel à la routine
int32 DllExport __CFUNC DAQmxBaseReadAnalogF64 (TaskHandle taskHandle, int32 numSampsPerChan, float64 timeout, bool32 fillMode, float64 readArray[], uInt32 arraySizeInSamps, int32 *sampsPerChanRead, bool32 *reserved);

et voici comment j'ai wrappé en rebol

ReadAnalogF64: make struct![
   {Reads multiple floating-point samples from a task that contains one or more analog input channels.}
   TaskHandle [integer!]
   numSampsPerChan [integer!]
   timeout [decimal!]
   fillMode [integer!]
   readArray [struct! [rval [double]]]
   arraySizeInSamps [integer!]
   sampsPerChanRead [struct! [spval [integer!]]]
   reserved [struct! [pnil [string!]]["0"]]; Reserved for future use. Pass NULL to this parameter
   return: [integer!]
] none
DAQmxBaseReadAnalogF64: make routine! ReadAnalogF64 nidll "DAQmxBaseReadAnalogF64"

Mon programme appelant passe une structure du type a: make struct! [val [double]] none à la fonction DAQmxBaseReadAnalogF64
On obtient bien des valeurs en récupérant ce qui est dans ReadArray
a/val ou third a fonctionnent et renvoient soit du décimal soit du binaire qui est effectivement en flottant double précision.J'ai vérifié avec la lib ieee.r.

mais les valeurs ne varient qu'entre 0 et 1.09 volts alors qu'on devrait obtenir des valeurs entre 0 et 5 volts (aorès conversion bien sûr).
Si tu as une idée lumineuse, elle est la bienvenue.
A +
guest210-Jan-2009/1:46:53+1:00
readArray est un pointeur de type integer! (32 bits) peu importe ce qu'il contient.
Tu fais probablement une erreur dans la manière de récupérer les valeurs double précision contenues à cette adresse, faudrait nous montrer ton code.
ldci10-Jan-2009/9:28:22+1:00
Salut Guest2
Tu as certainement raison pour l'erreur
Voici le code type du programme appelant
; pour les pointeurs
PData: make struct! [val [double]] [0.0]
PPointsRead: make struct! [val [integer!]] [0]
;null pointer for data acquisition
null: make struct! [nil [integer!]] none
; appel à la fonction
str: RGetExtendedErrorInfo DAQmxBaseReadAnalogF64 TaskHandle pointsToRead timeout DAQmx_Val_GroupByChannel PData samplesPerChan PPointsRead null
; str est une chaine contenant le numéro d'erreur renvyé par la dll
; on obtient 0: ce qui signifie que tout est OK
; je passe sur les autres paramètres qui sont initialisés correctement;

tmp: parse str ":"
ercode: to-integer first tmp
;récupération des valeurs
either ercode = 0 [acqval: PData/val * gain] [acqval: 0]
; on peut aussi écrire pour récupérer la valeur en binaire et la transformer en decimal
either ercode = 0 [acqval: to-decimal third PData* gain] [acqval: 0]
Voila et a première vue cela devrait fonctionner
Je suis preneur de toute solution.
Amicalement
guest210-Jan-2009/14:15:43+1:00
hum, y'a un truc que je pige pas.
si j'ai bien compris ReadArray renvoie un pointeur sur un tableau de doubles.
Et Arraysize est un entier qui contient la longueur du tableau.

Lors de l'appel, PData semble mal définit, il faut passer un pointeur pas un double.
PData: make struct! [val [char*]] none

De plus tu sembles avoir oublié de passer une variable pour récupérer la longueur du tableau (Array size).

En fait, tout semble fonctionner car au lieu de passer 2 variables séparées: un pointeur + la longueur du tableau (32bits + 32bits).
Tu récupères dans Pdata une valeur double précision (64 bits).
Donc en fait ton Pdata contient de façon concaténée un pointeur sur le tableau plus la longueur du tableau mais tu le traites comme si c'était une seule valeur décimale.

Donc ça semble normal que tu récupères n'importe quoi puisque tu ne le traites pas comme un tableau.

Avant d'aller plus loin, il faudrait précisemment savoir ce que renvoie RearArray. Est-ce un tableau (donc un pointeur) ou une simple valeur double précision ?
ldci10-Jan-2009/15:56:13+1:00
Re Guest2
Merci pour les infos
quelques comments:
PData est bien défini comme un pointeur non?
PData: make struct! [val [double]] [0.0]
ArraySize est également passé en pointeur
PPointsRead: make struct! [val [integer!]] [1]


voici un code en c qui fonctionne parfaitement (Mac ou Win) et qui me sert de base.Je suis sûr qu'avec ça tu vas m'éclairer.
Ce passage avec pointeur fonctionnait bien avec les anciennes libs de National Instruments


#include "NIDAQmxBase.h"
#include <stdio.h>

#define DAQmxErrChk(functionCall) { if( DAQmxFailed(error=(functionCall)) ) { goto Error; } }

int main(int argc, char *argv[])
{
// Task parameters
int32 error = 0;
TaskHandle taskHandle = 0;
char errBuff[2048]={'\0'};

// Channel parameters
char chan[] = "Dev1/ai0";
float64 min = -10.0;
float64 max = 10.0;

// Timing parameters
uInt64 samplesPerChan = 1;

// Data read parameters
float64 data;
int32 pointsToRead = 1;
int32 pointsRead;
float64 timeout = 10.0;

   //DAQmx_Val_Cfg_Default
DAQmxErrChk (DAQmxBaseCreateTask("",&taskHandle));
DAQmxErrChk (DAQmxBaseCreateAIVoltageChan(taskHandle,chan,"",DAQmx_Val_RSE,min,max,DAQmx_Val_Volts,NULL));
DAQmxErrChk (DAQmxBaseStartTask(taskHandle));
DAQmxErrChk (DAQmxBaseReadAnalogF64(taskHandle,pointsToRead,timeout,DAQmx_Val_GroupByChannel,&data,samplesPerChan,&pointsRead,NULL));

printf ("Acquired reading: %f\n", data);

Error:
if( DAQmxFailed(error) )
DAQmxBaseGetExtendedErrorInfo(errBuff,2048);
if( taskHandle!=0 ) {
DAQmxBaseStopTask(taskHandle);
DAQmxBaseClearTask(taskHandle);
}
if( DAQmxFailed(error) )
printf("DAQmxBase Error: %s\n",errBuff);
return 0;
}
guest210-Jan-2009/17:05:59+1:00
Apparement je parle chinois...

Ta définition en C

int32 DllExport __CFUNC DAQmxBaseReadAnalogF64 (
   1 TaskHandle taskHandle,
   2 int32 numSampsPerChan,
   3 float64 timeout,
   4 bool32 fillMode,
   5 float64 readArray[],    ->> pointeur 32 bits, à priori c'est la même chose que float64 *readArray (je hais le c++)
   6 uInt32 arraySizeInSamps,
   7 int32 *sampsPerChanRead,   ->> pointeur 32 bits
   8 bool32 *reserved
);

Ton utilisation en C
Tu a renommé les variables 2, 6 et 7 de manière confuse. On ne sait plus qui fait quoi.
Quelle est la variable qui contient la longueur du tableau ?
Quelles sont les variables en input et quelles sont celles en output ?

DAQmxBaseReadAnalogF64(
   1 taskHandle,
   2 pointsToRead,
   3 timeout,
   4 DAQmx_Val_GroupByChannel,
   5 &data,      ->> tu passes un pointeur, bien
   6 samplesPerChan,
   7 &pointsRead,      ->> là aussi
   8 NULL
);

Ton utilisation en Rebol.
Même confusion sur les noms.
De plus 5 et 7 doivent être des pointeurs. tu ne définis pas 5 correctement.
Un pointeur c'est une adresse qui a une taille fixe qui dépend de l'architecture.
Le Tableau qui contient des doubles a quand même une adresse sur 32 bits (le fait qu'il contienne des doubles ne rentre pas en ligne de compte)
Rebol 2 ne gère que des adresses 32 bits.
Donc PData doit avoir une taille de 32 bits, et pas 64 bits comme tu le fais actuellement.

RGetExtendedErrorInfo DAQmxBaseReadAnalogF64
   1 TaskHandle
   2 pointsToRead
   3 timeout
   4 DAQmx_Val_GroupByChannel
   5 PData   --> ça va pas, PData doit avoir une taille de 32 bits et pas de 64 bits
   6 samplesPerChan
   7 PPointsRead    --> là c'est bon
   8 null

Pour finir, je le répète...
PData: make struct! [val [double]] ne définit pas un pointeur 32 bits mais une valeur décimale de 64 bits
ldci10-Jan-2009/19:44:51+1:00
Merci Guest2 pour les précisions
Juste une chose, le code C est un exemple fourni par National Instruments qui d'ailleurs ne te donne qu'un NIDAQmxBase.h. Evidemment leur intérêt c'est de vendre LabView. La confusion des variables est leur.
Je vais corriger tt ça, mais encore merci pour les infos sur les pointeurs en Rebol.
A+
ldci1-Jun-2009/17:43:16+2:00
Toujours à propos de structures
voici un exemple
a: make struct! [val[integer!]] [1]
print ["testing Integer " mold a]
print ["Structure: " mold first a]
print ["Contenu: " second a]
print ["Contenu en binaire: " third a]
print ["Adresse en entier: " to-integer reverse third a]
print ["Taille en bytes: " length? third a]
print ["Contenu après appel à third: " second a]

et voici l'exécution du code
testing Integer make struct! [val [integer!]] [1]
Structure: [val [integer!]]
Contenu: 1
Contenu en binaire: #{00000001}
Adresse en entier: 16777216
Taille en bytes: 4
Contenu après appel à third: 16777216

Comme on peut le voir un second appel à second a après un reverse third a ne renvoie pas la même valeur.
Sin on fait la même chose avec un string à la place de l'integer, on obtient une belle "Segmentation Fault"
Je ne doute pas que les gourous qui sont sur ce site auront une explication.
A +
ldci2-Jun-2009/10:14:59+2:00
Bon finalement j(ai compris
en fait l'appel à reverse modifie effectivement l'ordre du contenu.
exemple
a: "1234"
probe reverse a >> "4321"
probe a >> "4321"
probe reverse a >> "1234"
probe a >> "1234"

Bon à savoir
A +

Login required to Post.


Powered by RebelBB and REBOL 2.7.8.4.2