Satimage Précédent | Suivant
Interfaçage de votre code avec AppleScript
Accueil Documentation Smile Calcul numérique Exploitation de programmes externes Les projets XCode Interfaçage de votre code avec AppleScript  
Note : pour ouvrir un fichier mentionné dans ces pages, ouvrez l'un des projets d'exemple et sélectionnez File > Open Quickly dans XCode, puis entrez le nom du fichier.

Introduction

Les appels entre applications ainsi que les commandes utilisées dans des scripts AppleScript sont gérés par un système d'événements appelés AppleEvents. Un AppleEvent est identifié par deux codes de 4 octets. Au niveau des scripts AppleScript, ces codes sont traduits dans une terminologie déterminée par un dictionnaire.

Un code scriptable est un exécutable capable de gérer des AppleEvents, et donc d'interagir avec des scripts AppleScript. Nos projets d'exemple fournissent des fonctions permettant de gérer simplement des AppleEvents, en gardant votre propre code indépendant de ces routines.

Vous trouverez ci-dessous deux liens vers des documentations externes (en anglais) concernant les applications scriptables et la communication entre applications :

Gestion des AppleEvents dans les projets d'exemple

La gestion des AppleEvents sera faite pour l'exemple de type SampleOsax dans le fichier nommé «NomDuProjet».cp, qui propose un schéma simple utilisant comme point d'entrée la fonction OsaxEventHandler. En ce qui concerne les projets d'applications scriptables, la gestion des AppleEvents est faite au niveau du fichier main.cp. Une grande partie de la gestion des AppleEvents est réalisée en appelant des fonctions définies dans les fichiers de Satimage includes, que vous n'aurez pas à modifier.
Vous trouverez plusieurs exemples de gestion des AppleEvents dans les différents projets fournis.

Un appel à votre code se traduira par un AppleEvent (identifié par deux codes de 4 octets) que vous intercepterez dans la fonction
pascal OSErr OsaxEventHandler(const AppleEvent* message, AppleEvent* reply, long refCon).
Dans nos projets, vous aurez à définir dans la variable globale EventDescription gEventDescriptionList[] la liste des événements qui pourront être gérés. Chacun des éléments de cette liste est composée de 3 éléments : les deux premiers correspondent aux deux codes de 4 octets identifiant l'AppleEvent, et le dernier est un entier qui sera passé à la fonction OsaxEventHandler via son argument refCon.

Les fonctions qui seront appelées à ce niveau ont deux arguments message et reply de type AppleEvent*, qui correspondent aux paramètres d'entrée et de sortie de l'interface AppleScript (à savoir, les paramètres de la fonction appelée d'une part, et d'autre part la réponse au format AppleScript renvoyée par cette fonction). Ce sont ces fonctions qui, après avoir traduit les arguments d'entrée dans des formats adéquats, appelleront votre code, puis géreront l'erreur éventuelle ou le résultat à renvoyer.

La structure de données AEDesc
La variable message contient un certain nombre d'objets, associés à des clés (des codes de 4 octets) qui correspondent aux différents paramètres de la fonction. Vous les obtiendrez généralement sous forme d'une structure de type AEDesc, qui est la structure correspondant aux variables AppleScript. (Note : les types AppleEvent et AEDesc sont équivalents.)
Vous aurez à gérer des AEDesc pour récupérer des données provenant d'AppleScript, et pour construire le résultat que vous voudrez renvoyer. Pour cela, vous utiliserez essentiellement les fonctions définies dans le fichier Satimage includes/AEDescUtils.h, par exemple AEDescToDouble ou FloatArrayToDesc.
Obtention des paramètres d'entrée
Pour récupérer un paramètre donné dans une AEDesc, on peut utiliser la fonction AEGetParamDesc (voir les exemples dans le code source fourni).
OSErr
AEGetParamDesc(
  const AppleEvent * theAppleEvent,
  AEKeyword theAEKeyword,
  DescType desiredType,
  AEDesc * result)
  • theAppleEvent est l'AppleEvent d'entrée, c'est-à-dire ici la variable message.
  • theAEKeyword est la clé correspondant au paramètre souhaité. Par exemple, pour obtenir le paramètre direct de la fonction appelée, il faut spécifier keyDirectObject. Cela peut être un code que vous avez défini vous-même (par exemple 'Par1') et qui correspondra à un paramètre défini dans le fichier .sdef.
  • desiredType est le type requis de la variable voulue. Si l'utilisateur a appelé la fonction avec un paramètre qui n'est pas du type requis, AEGetParamDesc essaiera d'effectuer une coercion vers ce type en utilisant les coercions disponibles dans AppleScript.
      Les constantes d'Apple correspondant à de nombreux types de données sont définis dans AEDataModel.h, par exemple typeChar, typeLongFloat, etc.
      le fichier Satimage includes/AEDescUtils.h rajoute des constantes correspondant aux deux types de données spécifiques à Smile : typeListOfLongFloat et typeMatrix.
  • result est l'AEDesc contenant le résultat
  • Si la fonction AEGetParamDesc n'arrive pas à obtenir le paramètre, elle renverra une erreur (par exemple, errAECoercionFail = -1700, ou encore errAEDescNotFound = -1701 ; ces erreurs sont listées dans le fichier MacErrors.h)
Fabrication du résultat retourné
Une fois votre code exécuté, vous voudrez retourner un résultat dans AppleScript. Ce résultat peut être n'importe quelle structure de donnée pouvant être contenue dans une AEDesc, c'est-à-dire un type simple d'Apple, un array of real, une matrix, ou encore une liste ou un record contenant des éléments de ce type. Il vous faudra définir une variable de type AEDesc, par exemple AEDesc resultDesc, à partir des données que vous voulez retourner, puis vous appellerez la fonction AEPutParamDesc(reply, keyAEResult, &resultDesc);
Gestion de la mémoire

En rendant votre code scriptable, vous vous apprêtez à pouvoir l'appeler autant de fois que nécessaire au cours d'une seule et même exécution. De ce fait, si dans certaines circonstances votre code fuit (s'il ne désalloue pas toute la mémoire qu'il a alloué à chaque appel), ou si la gestion de la mémoire n'est pas bien organisée (par exemple si votre code utilise une structure ou un pointeur qui a été désalloué dans un précédent appel), vous risquez de rencontrer des problèmes d'exécution tels que des ralentissements sensibles ou même des crashs.

Il est notamment nécessaire de libérer la mémoire allouée par une AEDesc en appelant la fonction AEDisposeDesc. Pour éviter de désallouer une zone de mémoire qui n'a pas été allouée, vous devrez initialiser vos AEDesc soit en appelant la fonction AEInitializeDesc ou en déclarant ainsi vos variables de type AEDesc :

AEDesc d={typeNull, 0};//initialisation
err=AEGetParamDesc(message, keyDirectObject, typeLongInteger, &d);//par exemple
AEDisposeDesc(&d); //désallocation de la mémoire
Gestion des erreurs

Au lieu de renvoyer un résultat, votre code peut renvoyer une erreur qui pourra être gérée par AppleScript. Il vous suffit de retourner un numéro d'erreur non nul dans la fonction appelée par OsaxEventHandler.
Cependant, il est très utile de personnaliser les messages d'erreur pour identifier les problèmes, tant pour le programmeur que pour les utilisateurs. Pour ce faire, vous pouvez utiliser deux fonctions définies dans Satimage includes/AEDescUtils.h :

  • OSErr PutReplyParamError(OSErr err,const AppleEvent* message,AppleEvent* reply,DescType key,DescType desiredType);, qui renvoie un message (du texte) identifiant un mauvais paramètre,
  • void PutReplyStringError(AppleEvent* reply, const char* strErr);, qui renvoie une erreur avec un texte que vous définissez.

Par exemple, si vous définissez une application MyApp ayant dans son dictionnaire AppleScript une fonction nommée MyFunction qui appelle votre code et qui renvoie une erreur comportant un numéro d'erreur et du texte, vous pouvez gérer l'erreur avec le script suivant :


try
     tell application "MyApp" to set x to MyFunction
on error s number n
     msg("error "& n & " : " &s)
end try

English version
Copyright ©2008 Paris, Satimage