; .EnTete "Le-Lisp (c) version 15.2" " " "Les structures C" ; .EnPied " " "%" " " ; .Chapitre S "Les structures C" ; ; .Centre "*****************************************************************" ; .Centre " Ce fichier est en lecture seule hors du projet ALE de l'INRIA. " ; .Centre " Il est maintenu par ILOG SA, 2 Avenue Gallie'ni, 94250 Gentilly " ; .Centre " (c) Le-Lisp est une marque de'pose'e de l'INRIA " ; .Centre "*****************************************************************" ; .Centre "$Header: cstruct.ll,v 4.2 88/12/07 22:43:47 kuczynsk Exp $" #| Ce chapitre de'crit la manipulation des structures C en Lisp sur les machines UNIX a` mots de 32 bits adressant l'octet. Il est possible de manipuler en Lisp, de la me↑me manie`re que les structures Lisp, des objets alloue's par des programmes C. L'utilisation des fonctions de'crites ci-dessous demande quelques pre'cautions\ : - Lorsque l'on stocke un objet Lisp dans une structure C il faut toujours garder un pointeur Lisp sur cet objet afin que le Garbage Collector (qui ne va pas visiter le contenu des structures C) ne re'cupe`re pas l'objet. - Il vaut mieux ne pas stocker de chai↑nes de caracte`res Lisp dans les structures C. Le Garbage Collector risquant de de'placer la chai↑ne de caracte`res dans le tas Lisp, Le pointeur C ne serait plus a` jour. Il est pre'fe'rable d'allouer une chai↑ne de caracte`res dans le tas C et d'y recopier la chai↑ne Lisp (voir la fonction CSTRING) Il faut aussi noter que la lecture et l'e'criture des champs des structures C ne sont pas des ope'rations tre`s efficaces. Si l'on de'sire manipuler intensivement les structures C il vaut mieux e'crire les parties de programmes concerne'es directement en C. L'interface avec les objets C utilise les primitives d'appel de proce'dures externes, de'crites au chapitre 14 du manuel de re'fe'rence. Elles permettent notamment de de'finir en Lisp diverses fonctions de'crites a` la fin de ce chapitre et permettant\ : - l'allocation de structures C dans une zone me'moire externe a` Le←Lisp (fonctions MALLOC et SIZEOF). - la libe'ration de ces structures (fonction FREE) - l'acce`s indexe' au niveau du caracte`re, du petit entier et du pointeur en lecture et en e'criture dans les structures C (fonctions LONG/SHORT/CHARREF et LONG/SHORT/CHARSET). .Section "De'finition de Structures C en Lisp" .Fonction "(DEFCSTRUCT <nom> (<taille1> <champ1>)...(<tailleN> <champN>)) \ \ \ [MACRO a` N arguments]" de'finit une structure C. <nom> est un symbole qui est le nom de la structure C. Les arguments <champI> sont des symboles nommant les champs, les arguments <tailleI> sont des symboles de'crivant la taill me'moire du i-e`me champ. Les symboles <tailleI> peuvent prendre l'une des trois valeurs suivantes\ : - LONG\ : le champ a alors la taille d'un pointeur - SHORT\ : le champ a alors la taille d'un entier court - CHAR\ : le champ a alors la taille d'un caracte`re. DEFCSTRUCT positionne enfin l'indicateur SIZEOF sur la PLIST du symbole <nom>, qui indique, en nombre de caracte`res, la taille me'moire occupe'e par une instance de la structure C (voir la fonction SIZEOF). .Fonction "(#:<nom>:MAKE) [SUBR a` 0 argument]" Alloue dans le tas C et retourne en valeur une nouvelle instance de la structure C <nom>. La fonction #:<nom>:MAKE est la fonction de cre'ation spe'cifique a` la structure <nom>. Elle est automatiquement de'finie par la fonction DEFCSTRUCT. L'objet cre'e' est un pointeur hors de la zone me'moire re'serve'e a` l'interpre`te Lisp, repre'sente' sous la forme d'un CONS de deux petits entiers. .DefLL "#:<nom>:MAKE" (DE #:<nom>:MAKE () (←MALLOC (SIZEOF '<nom>))) .FinLL .Fonction "(#:<nom>:<champI> <o> [<e>]) [SUBR a` 1 ou 2 arguments]" <nom> est le nom d'une structure C de'finie par la fonction pre'ce'dente, <champI> est le nom d'un champ de cette structure. Les fonctions #:<nom>:<champI> sont les fonctions d'acce`s aux champs des instances de la structure C <nom>. Elles sont de'finies automatiquement par la fonction DEFCSTRUCT. .Fonction "(SIZEOF <nom>) \ \ \ [SUBR a` 1 argument]" <nom> est un symbole repre'sentant le nom d'une structure C pre'de'finie pre'cedemment par la fonction DEFCSTRUCT. Retourne en valeur la taille me'moire utilise'e en me'moire par une instance de la structure C <nom>. Cette taille peut e↑tre fourni a` la fonction ←MALLOC pour allouer un vecteur d'objets C de type nom. Pour allouer un seul objet C on peut utiliser la fonction #:<nom>:MAKE. .pp \fIExemple\ :\fP Voici la de'claration C et la de'claration Lisp de la me↑me structure FontInfo\ : .DebLL typedef struct ←FontInfo { Font id; short height, width, baseline, fixedwidth; unsigned char firstchar, lastchar; short *widths; /* pointer to width array in OpenFont */ } FontInfo; (defcstruct FontInfo (long id) (short height) (short width) (short baseline) (short fixedwidth) (char firstchar) (char lastchar) (long widths)) .FinLL Voici la traduction en Lisp d'un programme C manipulant cette structure (on voit que la manipulation du vecteur de petits entiers fontinfo->widths ne'cessite la fonction ←WORDREF, de'crite plus bas)\ : .DebLL show←font (fontinfo) FontInfo *fontinfo; { char c; printf("Height %d, Width %d, Baseline %d\n", fontinfo->height, fontinfo->width, fontinfo->baseline); if (fontinfo->fixedwidth) printf("Fixedwidth font."); else for (c = fontinfo->firstchar; c <= fontinfo->lastchar; c++){ printf(" %c %d pixels\n", fontinfo->widths[c]); } (de show←font (fontinfo) (prinf "Height ~D, Width ~D, Baseline ~D" (#:FontInfo:height fontinfo) (#:FontInfo:width fontinfo) (#:FontInfo:baseline fontinfo)) (terpri) (if (neqn (#:FontInfo:fixedwidth fontinfo) 0) (print "Fixedwidth font.") (for (c (#:FontInfo:firstchar fontinfo) 1 (#:FontInfo:lastchar fontinfo)) (prinf " ~C ~D pixels" c (←shortref (#:FontInfo:widths fontinfo) (add c c))) (terpri)))) .FinLL .pp Ces fonctions sont de'finies en Lisp de la manie`re suivante\ : |# (unless (>= (version) 15.2) (error 'load 'erricf 'cstruct)) (add-feature 'cstruct) (when (eq 0 (getglobal '|←charref|)) (cload (catenate #:system:system-directory "o/cstruct.o"))) (setq #:sys-package:colon 'cstruct) (dmd defcstruct (name . fields) (let ((i 0) res) (setq fields (mapcar (lambda (field) (prog1 (cons i field) (incr i (cassq (car field) '((char . 1) (short . 2) (long . 4)))))) fields)) (while fields (newl res (:field-accessor name (nextl fields)))) `(progn ,@res (putprop ',name ,i 'sizeof) (de ,(symbol name 'make) () (|←malloc| ,i)) ',name))) (de :field-accessor (name (index size field-name)) `(de ,(symbol name field-name) (o . v) (ifn v (,(concat "←" size "ref") o ,index) (,(concat "←" size "set") o ,index (car v))))) (de sizeof (cstruct) (getprop cstruct 'sizeof)) #| .Section "Les Fonctions Primitives de Manipulation des Objets C" L'interface avec les structures C est base'e sur les fonctions primitives suivantes. Ces fonctions peuvent e↑tre utiles pour la manipulation des vecteurs d'objets C, comme de'crit dans l'exemple ci-dessous. On leur pre'fe`rera lorsque cela est possible les fonctions de la section pre'ce'dente. .Fonction "(←MALLOC <size>) \ \ \ [SUBR a` 1 argument]" Alloue <size> octets dans le tas C et retourne un pointeur externe (CONS de deux petits entiers pointant sur la zone alloue'e. .Fonction "(←FREE <external>) \ \ \ [SUBR a` 1 argument]" Rend au tas C les pointeur externe <external>. <External> doit evoir e'te' alloue' par la fontionc ←MALLOC, ou bien par une proce'dure C utilisant la fonction C malloc. .Fonction "(←CHARREF <external> <index>) \ \ \ [SUBR a` 2 arguments] .Fonction "(←SHORTREF <external> <index>) \ \ \ [SUBR a` 2 arguments] .Fonction "(←LONGREF <external> <index>) \ \ \ [SUBR a` 2 arguments] <external> est un pointeur dans le tas C, ou bien sur une structure C rec,ue d'un programme C exte'rieur a` Le←Lisp. Retourne les 8(CHAR), 16(SHORT) ou 32(LONG) bits pris a` l'adresse <external>+<index>, <index> e'tant exprime'e en octets. .Fonction "(←CHARSET <external> <index> <value>) \ \ \ [SUBR a` 3 arguments] .Fonction "(←SHORTSET <external> <index> <value>) \ \ \ [SUBR a` 3 arguments] .Fonction "(←LONGSET <external> <index> <value>) \ \ \ [SUBR a` 3 arguments] <external> est un pointeur dans le tas C, ou bien sur une structure C rec,ue d'un programme C exte'rieur a` Le←Lisp. Stocke les 8(CHAR), 16(SHORT) ou 32(LONG) bits les moins significatifs de la valeur <value> a` l'adresse <external>+<index>, <index> e'tant exprime'e en octets. .Fonction "(←CSTRING <string>) \ \ \ [SUBR a` 1 argument]" Alloue (add1 (LEN <string>)) caracte`res dans le tas C, y recopie le contenu de la chai↑ne Lisp <string> et retourne un pointeur sur la zone me'moire alloue'e. Cette fonction permet de recopier dans le tas C les chai↑nes de caracte`res Lisp, ce uqi est ne'cessaire si l'on de'sire passer a` C des chai↑ne qui ne doivent pas e↑tre de'place'es elors des re'cupe'rations. .DebLL ex: ; La proce'dure C XMenuInsertSelection rec,oit rec,oit une chai↑ne de ; caracte`res de'crivant le nom d'un item a` rajouter au menu. Cette chai↑ne ; ne doit pas bouger lors des re'cupe'rations Lisp. Il faut donc la recopier ; dans le tas C avant de la passer a` la proce'dure /* fichier C */ int XMenuInsertSelection (menu, pane, selection, data, label, active) XMenu *menu; int pane, selection; caddr←d data; char *label; int active; \&... #\&| fichier Lisp |\&# (defextern ←XMenuInsertSelection (external fix fix t external fix) fix) ; on donne le type external a` l'argument label (char *) (de make-menu strings ... (←XMenuInsertSelection menu 0 0 0 (←cstring (nextl strings)) 1) ... .FinLL .pp Malloc et Free sont les fonctions C du manuel de re'fe'rence UNIX (3). Les autres fonctions sont des de'finitions externes des fonctions C de'crites ci-dessous\ : .DebLL charref (s, n) char *s; { return * (char *) (s + n); } shortref (s, n) char *s; { return * (short *) (s + n); } longref (s, n) char *s; { return * (int *) (s + n); } charset (s, n, v) char *s; { *(char *) (s + n) = v; } shortset (s, n, v) char *s; { *(short *) (s + n) = v; } longset (s, n, v) char *s; { *(int *) (s + n) = v; } char *cstring (lispstring, length) char *lispstring; { char *s = (char *)malloc (length+1); strncpy (s, lispstring, length+1); return s; } .FinLL |# (defextern |←malloc| (fix) external) (defextern |←free| (external)) (defextern |←charref| (external fix)) (defextern |←shortref| (external fix)) (defextern |←longref| (external fix) external) (defextern |←charset| (external fix fix)) (defextern |←shortset| (external fix fix)) (defextern |←longset| (external fix external)) (defextern |←cstring| (string fix) external)