Project

General

Profile

Coder une bibliothèque Scol en C - Niveau 3 » History » Version 1

iri, 01/29/2013 10:09 PM

1 1 iri
h1. Coder une bibliothèque Scol en C - Niveau 3
2
3
Objectif : nouvel objet Scol, fonctions callbacks
4
5
Moyens :
6
7
* définir un nouveau type Scol;
8
* fonctions de création et de destruction d'un objet;
9
* manipulation de l'objet;
10
* fonctions réflexes (callbacks) sur cet objet;
11
* intégration simple de la librairie "libcurl":http://curl.haxx.se/libcurl/;
12
* code source de la bibliothèque;
13
* exemple d'utilisation dans une application Scol.
14
15
STATUT : COMPLET
16
Version : 1.0
17
Date : Novembre 2010 (initialement diffusé sur http://www.irizone.net)
18
Auteur : iri
19
Licence du tutoriel : GNU FDL v1.3
20
Licence du code source : GNU/GPL v3
21
Téléchargement : http://www.irizone.net/dl/tutos/vmscol/vm_example_3.tar.gz
22
Langage : *C*
23
Ok pour toute version de Scol Windows et GNU/Linux (> 4.0).
24
25
h2. La bibliothèque _libcurl_, exemple d'intégration
26
27
"Libcurl":http://curl.haxx.se/libcurl/ est une bibliothèque "libre":http://curl.haxx.se/docs/copyright.html
28
et gratuite pour de très nombreux systèmes et langages. Elle est très utilisée et
29
a atteint un bon degré de robustesse. Elle est capable d'utiliser de nombreux
30
protocoles, sous divers formats.
31
32
En Scol, les connexions au réseau sont actuellement codées en bas niveau, grâce 
33
aux sockets. Peu de protocoles sont disponibles (http et telnet) et sous certaines 
34
conditions. Utiliser une telle librairie de plus haut niveau permettrait de s'affranchir
35
du code bas niveau, toujours plus fastidieux, d'intégrer une biliothèque robuste
36
et éprouvée et d'élargir les capacités de Scol. En contrepartie, son utilisation
37
rend Scol plus dépendant. C'est pourquoi les "anciennes" fonctions ne devraient
38
pas être dépréciées.
39
40
h3. Comment intégrer une telle bibliothèque ?
41
42
Au niveau de Scol, il n'y a rien de particulier à faire. Au niveau du code
43
source, il faut bien évidemment inclure les fichiers d'en-tête nécessaires. Au
44
niveau du binaire à diffuser, deux solutions s'offrent à vous :
45
46
# inclure la bibliothèque dans la votre. Cela rend l'utilisateur final indépendant,
47
il n'a pas à installer libcurl de façon disjointe. Cependant, s'il la possède déjà,
48
c'est un peu inutile. De plus, le poids de votre bibliothèque sera plus important.
49
# ne pas inclure la bibliothèque dans la votre. Cela la rendra plus légère au
50
niveau du poids et si l'utilisateur final la possède déjà, il n'y aura pas d'effet
51
doublon. En revanche, s'il ne la possède pas, elle ne fonctionnera pas tant qu'il
52
ne l'aura pas installé.
53
54
Il n'y a pas de solutions idéales mais un compromis à faire. À vous de voir.
55
56
h3. Exemple : Se connecter à un serveur et récupérer un fichier
57
58
Il s'agit de l'utilisation la plus simple de libcurl : lui donner une url et
59
enregistrer la réponse du serveur dans un fichier local. Nous allons donc le faire.
60
61
Il n'y a rien de particulier par rapport à ce qui a été vu dans les niveaux
62
précédents. Le reste du code C est pour appeler et interfacer la bibliothèque libcurl.
63
64
# On récupère les données depuis la pile Scol et on teste leur validité;
65
# On initialise la bibliothèque;
66
# On alloue dynamiquement nos ressources (il ne faudra donc pas oublier de les
67
libérer !);
68
# On envoie la requête à libcurl et on définit la callback d'écriture des données
69
reçues. À ce sujet, nous ne verrons pas ici (mais plus bas dans ce tutoriel)
70
l'ajout d'une callback Scol. C'est libcurl qui se chargera d'écrire dans notre
71
fichier. En effet, par défaut, celle-ci écrit les données reçues dans un fichier
72
(et si ce fichier n'est pas défini, ce sera sur la sortie standard).</li><br />
73
# Nous libérons nos ressources;
74
# Nous empilons notre réponse dans la pile Scol.
75
76
La fonction Scol retournera 0 si tout s'est correctment passé. Autrement, nil
77
sera retourné si l'url ou le fichier local valent eux-même nil, si le fichier local
78
ne peut être ouvert en écriture ou si la libcurl n'a pas pu s'initialiser. Dans les
79
autres cas, elle retournera un entier positif indiquant le type d'erreur que
80
libcurl a rencontré. Pour avoir une liste complète des erreurs possibles, consultez
81
cette "page":http://curl.haxx.se/libcurl/c/libcurl-errors.html.
82
83
Notez que plus loin une méthode plus conviviale de gestion des erreurs sera
84
proposée (voir dans l'archive téléchargeable).
85
86
Code source de la fonction :
87
88
<pre>int sc_getFile (mmachine m)
89
{
90
    int murl, mlocalfile, len;
91
    char * url, * localfile, * err = NULL;
92
93
    CURL * hCurl;     /* handle système */
94
    CURLcode rCurl;   /* result */
95
    FILE * fp = NULL;
96
97
    MMechostr (MSKDEBUG, "sc_getFile : entering ...n");
98
99
    mlocalfile = MTOP (MMpull (m));
100
    murl = MTOP (MMpull (m));
101
102
    if ((mlocalfile == NIL) || (murl == NIL))
103
    {
104
        MMechostr (MSKDEBUG, "sc_getFile error : url or localfile is niln");
105
        MMpush (m, NIL);
106
        return 0;
107
    }
108
109
    hCurl = curl_easy_init();
110
    if (hCurl)    /* init ok */
111
    {
112
        /* Nous n'avons pas besoin d'avoir cette donnée dans la pile,
113
        nous n'utilisons donc pas les fonctions d'allocation de la machine Scol
114
        mais les fonctions d'allocation (et de libération) standard du C.*/
115
        len = sizeof (char) * (MMsizestr (m, mlocalfile));
116
        localfile = (char *) malloc (len+1);
117
        strncpy (localfile, MMstartstr (m, mlocalfile), len);
118
        localfile[len] = '\0';
119
120
        fp = fopen (localfile, "w");
121
        if (fp == NULL)
122
        {
123
            curl_easy_cleanup (hCurl);
124
            free (localfile); localfile = NULL;
125
            MMpush (m, NIL);
126
            return 0;
127
        }
128
129
        err = (char *) malloc (sizeof (char) * (CURL_ERROR_SIZE +1));
130
        len = sizeof (char) * (MMsizestr (m, murl));
131
        url = (char *) malloc (len+1);
132
        strncpy (url, MMstartstr (m, murl), len);
133
        url[len] = '\0';
134
135
        curl_easy_setopt (hCurl, CURLOPT_URL, url);
136
        curl_easy_setopt (hCurl, CURLOPT_WRITEFUNCTION, fwrite);
137
        curl_easy_setopt (hCurl, CURLOPT_WRITEDATA, (FILE *) fp);
138
        curl_easy_setopt (hCurl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
139
        curl_easy_setopt (hCurl, CURLOPT_ERRORBUFFER, err);
140
        rCurl = curl_easy_perform (hCurl);
141
142
        MMechostr (MSKDEBUG, "sc_getFile : err = %s ...n", err);
143
        curl_easy_cleanup (hCurl);
144
        fclose (fp);
145
146
        free (localfile); localfile = NULL;
147
        free (url); url = NULL;
148
        free (err); err = NULL;
149
150
        MMpush (m, ITOM (rCurl));
151
        return 0;
152
    }
153
154
    MMpush (m, NIL);
155
    return 0;
156
}</pre>
157
158
159
h3. Exemple d'utilisation avancée
160
161
h4. Nouveau type Scol
162
163
À présent, nous allons voir comment ajouter un nouveau type Scol et comment
164
gérer des callbacks Scol, le tout en utilisant libcurl comme fil rouge.
165
166
Pour créer un nouveau type Scol, il faut :
167
168
# L'enregistrer au sein de la machine Scol, afin qu'il soit connu;
169
# Le paramétrer et, notamment, définir sa fonction de destruction (ou plus
170
exactemement sa fonction réflexe de destruction).
171
172
L'enregistrement se réalise grâce à la fonction _OBJregister_ : elle est
173
définie dans le kernel, au sein du fichier "kernel/scolobj.c".
174
175
Elle prend 4 arguments :
176
177
# Le nombre de callbacks attendues, associées aux objets Scol de ce type. Si vous
178
définissez par exemple 4 callbacks associées aux objets de ce type (par exemple,
179
création, destruction, affectation et récupération), alors il faudra indiquer 4;
180
# Un flag indiquant si les objets de ce type sont détruits si leur objet parent
181
est détruit (si un tel type objet parent est défini, ce qui est rare). Généralement,
182
on laisse à 1, ce qui implique la destruction si le parent est détruit (et comme
183
il n'y a généralement pas de parent, cela ne change rien !);
184
# La callback interne de destruction, appelée lorsqu'un objet de ce type est
185
implicitement ou explicitement détruit;
186
# Le nom interne de ce type (qui sera utilisé dans certains cas particuliers, autant
187
lui donner un nom suffisamment explicite).
188
189
Par exemple :
190
<pre>#define NB_REFLEX 4
191
int MyObjectType;
192
MyObjectType = OBJregister (NB_REFLEX, 1, MyObjTypeDestroy, "MyNewObjectType");
193
</pre>
194
195
h4. Comment est définie la callback de destruction ?
196
197
Son prototype C est :
198
199
@int MyObjTypeDestroy (mmachine, int, int);@
200
201
Son premier argument est bien sur la machine Scol concernée, son second est le
202
pointeur vers l'objet système et le troisième est le pointeur vers l'objet Scol. 
203
Cette fonction n'a théoriquement pas à être appelée directement, son appel devrait 
204
rester transparente pour le programeur.
205
Nous pouvons lui faire faire tout un tas de choses, selon les cas. De manière 
206
générale, son application minimale consiste à supprimer la référence de l'objet
207
dans la machine Scol, via _MMstore_ à NULL. Le code habituellement minimal est le suivant :
208
209
<pre>int MyObjTypeDestroy (mmachine m, int handlesys, int handlem)
210
{
211
    TYPE_C * obj;
212
213
    obj = (TYPE_C *) MMfetch (m, MTOP (handlem), OBJTYPE_C_HANDLE);
214
    if (obj == NULL)
215
    {
216
        MMechostr(MSKDEBUG, "MyObjTypeDestroy : object already destroyedn");
217
        return 0;
218
    }
219
220
    MMstore (m, MTOP (handlem), OBJTYPE_C_HANDLE, (int) NULL);
221
    MMechostr(MSKDEBUG, "MyObjTypeDestroy: object has been destroyedn");
222
223
    return 0;
224
}</pre>
225
226
Le flag _OBJTYPE_C_HANDLE_ est un flag utilisé lors de la création de l'objet, ce que nous verrons ci-après.
227
228
h4. Nouvel objet Scol
229
230
Pour créer un objet d'un type Scol, il est nécessaire de suivre ces étapes :
231
232
# Création de l'objet système (en C ou en C++), avec tout ce que cela peut impliquer.
233
Ici, l'utilisation de libcurl va nous simplifier la tâche et nous n'aurons donc
234
pas à coder des processus de plus ou moins bas niveaux comme l'allocation mémoire
235
et tout le reste;
236
# Allouer la mémoire au sein de la machine Scol. Nous utiliserons pour cela la
237
fonction <em>MMalloc</em> (ne confondez pas avec l'allocation système, via malloc);
238
# Stocker l'objet dans la machine Scol, grâce à la fonction _MMstore_;
239
# Empiler l'objet  dans la pile Scol, afin de le rendre disponible au programmeur
240
Scol (_MMpush_);
241
# Créer la référence de l'objet avec le nouveau type avec OBJcreate.
242
243
Exemple :
244
245
<pre>sizetab = sizeof (TYPE_OBJECT_C) + 1;
246
objtab = MMalloc (m, sizetab, TYPETAB);
247
if (objtab == NIL)
248
{
249
	MMpush (m, NIL);
250
	return 0;
251
}
252
MMstore (m, objtab, OBJTYPE_C_HANDLE, (int) handle_sys);
253
MMpush (m, PTOM (objtab));
254
OBJcreate (m, MyObjectType, (int) handle_sys, parent_type, parent);</pre>
255
256
_MMalloc_ prend donc trois arguments. Les deux premiers sont logiques :
257
respectivement la machine Scol dans laquelle allouée et la taille à allouer. Le 
258
troisième est un flag qui peut prendre la valeur de TYPETAB (array) ou TYPEBUF 
259
(buffer).
260
261
_MMstore_ attend 4 arguments : la machine Scol, le pointeur qui vient
262
d'être alloué et qui contiendra l'objet, un flag spécifique que vous définissez 
263
vous-même et le pointeur système pour la liaison.
264
265
_MMpush_ empile le pointeur de l'objet (normal !).
266
267
_OBJcreate_ s'approprie 5 arguments : la machine Scol, une variable
268
interne qui contient le type Scol, le pointeur système et, de façon optionnelle,
269
le type de l'objet parent et le parent lui-même, s'il y a lieu (sinon, une valeur
270
comme -1 ou NIL pour ses deux derniers convient).
271
272
Il y a un élément dont nous n'avons absolument pas parler, c'est le canal, qui est
273
à la base de Scol, dans lequel cet objet doit être crée. Il est *impératif*
274
qu'il soit parmi les éléments de la pile, typiquement présent dans les arguments
275
de la fonction Scol appelant à la création de l'objet. Lors de l'appel à OBJcreate,
276
il *faut* que le canal considéré soit à l'étage 1 de la pile, l'étage
277
0 étant occupé par le pointeur objet (MMpush précédent). Si le canal n'est pas présent
278
à cet étage 1 (assurez vous en !), vous devez l'y placer, grâce à MMset ou à la macro
279
INVERT suivant les cas. Ou, à défaut, en récupérant le canal courant dans la pile.
280
N'oubliez pas !
281
282
L'histoire du canal est cruciale. C'est la principale raison de plantage ou de
283
non création d'objet lorsque vous testerez votre code. Le canal n'est jamais
284
explicitement utilisé et il est ainsi facilement oublié. Il convient également
285
de tester sa validité <strong>avant</strong> toutes manipulations de création C ou
286
Scol. De plus, ce test permet de ne pas l'oublier ....
287
288
En étudiant le code existant, la "ruse" suivante est souvent utilisée : tous
289
les arguments envoyés par la fonction Scol sont dépilés (MMpull) excepté le dernier
290
(qui est donc le prmier argument dans la fonction Scol). Remarquez que ce premier
291
argument est le canal. Ainsi, alors qu'on a utilisé MMpull pour les autres arguments,
292
l'utilisation de MMget (m, 0) pour tester le canal permet de le garder à l'étage 0.
293
Ensuite, grâce au MMpush sur le pointeur, il remonte à l'étage 1 ...:) Ceci dit,
294
cette technique n'est pas toujours faisable et nous ne l'appliquerons pas.
295
296
h4. Ajouter une callback à un objet Scol
297
298
Lorsqu'on crée un objet Scol, il est généralement utile de lui associer une
299
ou plusieurs fonctions réflexes pour traiter des évènements.
300
301
Cela passe par _OBJaddreflex_ avec ses trois arguments : la machine Scol,
302
la variable qui contient le type Scol et un flag spécifique à votre callback.
303
Ce flag, vous le définissez vous-même et sa valeur devrait être inférieure au nombre
304
total de callbacks définis pour ce type Scol (voir plus haut la création d'un type
305
Scol avec _OBJregister_). Dans un exemple donné lui aussi plus haut, nous
306
avions défini 4 callbacks pour un type Scol (création, destruction, affectation et 
307
récupération). Nous pourrions alors définir (via un simple <code>#define</code>)
308
la valeur 0 pour la création, 1 pour la destruction, 2 pour l'affectation et 3 
309
pour la récupération.
310
311
La configuration de la callback se fait donc en amont de cet appel, par
312
empilement ou affectation dans la pile. Nous avons vu tout à l'heure la position
313
du canal dans la pile lors de la création d'un objet. C'est un peu la même chose ici.
314
À l'étage 2 doit se trouver l'objet de type Scol,
315
À l'étage 1 doit se trouver la référence à la callback (le _@myCallback_
316
dans les arguments de la fonction Scol),<br />
317
À l'étage 0 doit se trouver le paramètre utilisateur, laissé à la discrétion du
318
programmeur Scol.
319
Là encore, si nécessaire, usez de la fonction MMset ou de la macro INVERT.
320
321
Par exemple, soit la fonction Scol  <em>_CBfunction</em> qui demande en argument :
322
l'objet d'un type A, une fonction callback et un paramètre utilisateur. C'est un cas
323
fréquent dans l'API Scol. Nous avons en langage Scol :
324
325
<pre>typeof objA = A;;
326
...
327
_CBfunction objA @cbA "toto";
328
...</pre></code>
329
Le pseudo-code C correspondant à _CBfunction :
330
<code><pre>CBfunction (mmachine m)
331
{
332
	int mobj;
333
	mobj = MTOP (MMget (m, 2));
334
	if (mobj == NIL)
335
		return 0
336
	OBJaddreflex (m, typeA, FLAG_CB_TYPE_A);
337
	return 0;
338
}</pre>
339
340
h4. Appeler une callback d'un objet Scol
341
342
Avant d'appeler une telle callback, il convient de s'assurer qu'elle existe !
343
Si tel est le cas, elle est "préparée" à être exécutée puis enfin lancée.
344
345
Pour tester sa présence et la préparer éventuellement, _OBJbeginreflex_ est prévue.
346
Elle attend quatre argument : la machine Scol, la variable contenant le type objet
347
concerné, le pointeur système et le flag qui a servi à l'ajouter (voir ci-dessus).
348
Les premier, second et quatrième arguments sont aisément accessibles.
349
Le troisième, le pointeur système de l'objet Scol, est parfois plus retors. On
350
peut faire en sorte qu'il soit inclus dans la pile, à une position connue. Ce
351
n'est cependant pas toujours réalisable lorsqu'une bibliothèque tierce gère les
352
évènements de l'objet. Plusieurs méthodes s'offrent à vous ; nous emploierons ici
353
une structure qui le contiendra et qui sera passé en paramètre de la fonction tierce.
354
355
_OBJbeginreflex_ doit retourner 0 en cas de succès. N'oubliez donc pas de tester 
356
son retour.
357
358
<pre>int cb = 0;
359
cb = OBJbeginreflex (m, MyObjectType, (int) handle_sys, FLAG_CB_TYPE_A);
360
if (cb)	/* pas de callback définie dans le script Scol */
361
	return 0;</pre>
362
	
363
Une fois la callback préparée, il ne reste plus qu'à l'appeler avec <em>OBJcallreflex</em>.
364
Celle-ci ne prend que deux arguments : la machine Scol et le nombre de paramètres
365
supplémentaires de la callback.
366
367
h5. Arguments ?
368
369
Que sont ces paramètres supplémentaires de la callback ?
370
371
Toutes les callbacks Scol ont au moins deux arguments : l'objet Scol sur lequel
372
l'évènement a été généré et le paramètre utilisateur, paramètre à la convenance
373
du développeur Scol.
374
Il est tout à fait possible de donner au programmeur Scol d'autres paramètres.
375
Par exemple, lors d'un clic sur un objet Scol graphique, il est probablement
376
intéressant non seulement de fournir les deux paramètres cités mais aussi d'y adjoindre
377
les coordonnées du clic, du bouton de la souris qui a été cliqué, etc. Ce sont ça
378
les <em>paramètres supplémentaires</em>.
379
380
Reprenons notre exemple de clic dans un élément graphique. Nous désirons joindre
381
les coordonnées du clic (x, y), le bouton de souris (button) et la touche de clavier
382
éventuellement appuyée (mask). Nous pouvons décider que chacune de ces informations
383
correspondra à un argument de la callback : x y button mask. Cela fera donc 4 paramètres
384
supplémentaires. Nous pouvons aussi décider de grouper les coordonnées en un seul argument
385
pour former un tuple : [x y] button mask. Cela fera donc 3 arguments supplémentaires.
386
Ou encore de les regrouper tous en un seul tuple : [[x y] button mask]. Cela fera
387
1 argument supplémentaire.
388
389
Bien entendu, il peut très bien n'y avoir aucun paramètres supplémentaires à 
390
transmettre et nous noterons, dans ce cas, 0.
391
392
Ces fameux paramètres doivent être connus de la pile Scol lors de l'appel à
393
_OBJcallreflex_. Vous devez donc, si ce n'est déjà fait, les empiler au
394
préalable. Cela se code de la façon habituelle (MMpush avec construction de
395
tuple(s) ou de liste(s) éventuel(s)). Cet empliment doit se faire dans l'ordre
396
des arguments de la callback.
397
398
Avec notre exemple précédent :
399
<pre>int cb;
400
cb = OBJbeginreflex (m, MyObjectType, (int) handle_sys, FLAG_CB_TYPE_A);
401
if (cb)
402
{
403
	MMechostr ("No callback ...n");
404
	MMpush (m, NIL);
405
	return 0;
406
}
407
MMpush (m, ITOM (x));
408
MMpush (m, ITOM (y));
409
MMpush (m, ITOM (button));
410
MMpush (m, ITOM (mask));
411
OBJcallreflex (m, 4);</pre>
412
413
donnera un prototype Scol : <code>fun [ObjTypeA u0 I I I I] u1</code>
414
ou
415
416
<pre>int cb;
417
cb = OBJbeginreflex (m, MyObjectType, (int) handle_sys, FLAG_CB_TYPE_A);
418
if (cb)
419
{
420
	MMechostr ("No callback ...n");
421
	MMpush (m, NIL);
422
	return 0;
423
}
424
MMpush (m, ITOM (x));
425
MMpush (m, ITOM (y));
426
MMpush (m, ITOM (2));
427
MBdeftab (m);
428
MMpush (m, ITOM (button));
429
MMpush (m, ITOM (mask));
430
OBJcallreflex (m, 3);</pre><
431
432
donnera un prototype Scol : <code>fun [ObjTypeA u0 [I I] I I] u1</code>
433
ou encore
434
435
<pre>int cb;
436
cb = OBJbeginreflex (m, MyObjectType, (int) handle_sys, FLAG_CB_TYPE_A);
437
if (cb)
438
{
439
	MMechostr ("No callback ...n");
440
	MMpush (m, NIL);
441
	return 0;
442
}
443
MMpush (m, ITOM (x));
444
MMpush (m, ITOM (y));
445
MMpush (m, ITOM (button));
446
MMpush (m, ITOM (mask));
447
MMpush (m, ITOM (4));
448
MBdeftab (m);
449
OBJcallreflex (m, 1);</pre>
450
451
donnera un prototype Scol : <code>fun [ObjTypeA u0 [I I I I]] u1</code>
452
453
h4. Détruire un objet Scol
454
455
Lors de la création d'un nouveau type, nous avons codé une callback de destruction.
456
Cette dernière sera appelée à chaque objet de ce type détruit. Mais comment détruire
457
un tel objet une fois que le programmeur Scol n'en a plus besoin ?
458
459
C'est très simple. La fonction _OBJdelTM_ est faîte pour ça ! Elle prend
460
3 arguments : la machine Scol, le flag utilisé lors de la création (étape de stockage
461
avec _MMstore_) et le pointeur Scol de l'objet (c'est bien le pointeur
462
Scol et non le pointeur système qui est attendu).
463
464
Généralement, les fonctions Scol de destruction ne prennent qu'un seul argument :
465
l'objet à détruire. Le code minimal est alors :
466
467
<pre>int obj;
468
obj = MTOP (MMpull (m));
469
if (obj == NIL)
470
{
471
	MMechostr ("Object already destroyedn");
472
	MMpush (m, NIL);
473
	return 0;
474
}
475
OBJdelTM (m, OBJTYPE_C_HANDLE, PTOM (obj));
476
MMpush (m, 0);
477
return 0;</pre>
478
479
h2. Code source complet
480
481
Il est trop long pour être écrit sur cette page déjà ... longue ! Veuillez donc
482
vous reporter à l'archive associée à ce tutoriel (en haut de page).
483
484
Si vous souhaitez le compiler, n'oubliez pas d'indiquer à votre compilateur les
485
headers de libcurl et de linker vers les librairies de libcurl. Le linkage peut
486
se faire simplement avec un <code>-lcurl</code>. 
487
"Curl-config":http://curl.haxx.se/libcurl/using/curl-config.html peut
488
vous apporter une aide précieuse.
489
490
À l'exécution, si vous avez décidé de ne pas inclure libcurl à votre bibliothèque,
491
il faudra avoir préalablement installé les binaires libcurl sur la machine de test.
492
Sous GNU/Linux, l'installation du paquet libcurl de votre distribution est
493
suffisante. Pour MS Windows, les quatre dll suivantes sont requises pour tester
494
cet exemple (mais si vous rajoutez des fonctionalités, d'autres pourront être
495
nécessaires) : libcurl.dll, libeay32.dll (ou 64 sur 64 bits), libidn-11.dll,
496
libssl32.dll (64 sur 64 bits).
497
498
h2. Exemple de code Scol</h2>
499
500
<pre>typeof w_file = W;;
501
502
fun cbNewUrl (objCurl, user_param, data_received, size_data, url, error)=
503
	_appendpack data w_file;
504
	_fooS user_param;
505
	0;;
506
507
fun main ()=
508
	_showconsole;
509
	
510
	set w_file = _getmodifypack "tests/seeks.txt";
511
	example_getFile 
512
		"http://www.seeks.fr/" 
513
		w_file;
514
	
515
	_fooS "example_getFile : ok !";
516
	
517
	example_newUrl 
518
		_channel 
519
		"http://www.seeks.fr/search?q=irizone&expansion=1&action=expand"
520
		nil
521
		@cbNewUrl
522
		"Youpi !!";
523
		
524
	_fooS "example_newUrl : ok !";
525
	0;;
526
</pre>
527