[EN] [IT]
  [INFO] [ACQUÉRIR] [PLAN] [RESSOURCES]




PORTAGE DE VOS ANCIENS PROGRAMMES VERS CARBON

Carbon est une librairie, appelée CarbonLib et produite par Apple, qui modernise et étend la Toolbox du Macintosh telle que nous avons appris à la connaître et à l'aimer. Pour peu que l'extension CarbonLib soit présente dans votre dossier Système (ou celui de votre utilisateur final), vos applications s'exécuteront en mode natif sur tous les systèmes de Mac OS 8.5 à sa plus récente version [9.2 au moment où ces lignes sont rédigées]. Dans Mac OS , les applications carbonisées s'exécutent en mode natif.

Dans OS X, lorsque vous exécutez une application PPC ou 68K réalisée avec une ancienne release de FutureBASIC, l'environnement Classic est invoqué (cet environnement est en principe installé en accompagnement de OS X) de telle sorte que votre application continue à fonctionner mais dans une boîte de compatibilité.
La Release 6 vous permet de vous débarrasser de cette couche de compatibilité lorsque vous exécutez vos applications compilées. Mais, veuillez garder à l'esprit que l'environnement de développement FutureBASIC^3 n'est pas encore carbonisé, et que l'Editeur, le Compilateur et Program Generator s'exécutent quant à eux dans l'environnement Classic sous OS X. Toutefois, votre application Carbon s'exécutera comme n'importe quelle autre application écrite pour Mac OS X.

Cela dit, programmer pour Carbon est une expérience nouvelle. Pour exploiter les avantages de Mac OS X, divers aspects de la Toolbox ont dû être changés. Ainsi, si votre programme repose énormément sur la Toolbox, vous devrez tenir compte de certains de ces changements.

En tout état de cause, s'attendre à voir tourner sans problèmes un programme aux dizaines de milliers de lignes de code, juste en sélectionnant un article de menu, n'est pas vraiment raisonnable. Il n'est pas interdit de caresser ce doux rêve, mais si vous ne voulez pas qu'il se transforme en cauchemar, continuez à lire. Il est même probable que vos premières tentatives aboutissent à des plantages, cependant vos crashes n'auront aucune incidence sur les autres applications actives ni sur le Système, et ce, grâce à la protection de la mémoire de Mac OS X.

Ci-dessous, vous trouverez une liste des points à vérifier pour savoir si votre programme a besoin d'être mis à jour...


Alain Pastor:
Paris, 25/02/2002

[haut de la page]

Globales en mémoire basse (Low Memory Globals)

On a pris l'habitude de lire et d'écrire certaines valeurs dans un espace global réservé au Système, en PEEKant ou POKant simplement ces valeurs à des adresses référencées par des constantes du système. Par exemple, nous pouvions retrouver la hauteur en pixels de la barre de menus avec l'instruction suivante :

hauteur% = PEEK WORD (_mBarHeight)

ou plus souvent nous utilisions le raccourci suivant :

hauteur% = {_mBarHeight}

Voilà une violation directe de la mémoire protégée que Mac OS X a apportée à nos machines, et en tant que telle, ce genre d'instruction est vouée, aussitôt qu'elle est exécutée, à planter notre application. Heureusement, le Compilateur vous gratifiera d'un avertissement si vous tentez de compiler pour Carbon un programme qui contient des constantes obsolètes.

La solution est plutôt simple : pour la plupart de ces valeurs globales, Apple fournit maintenant des fonctions spécifiques. Il s'agit simplement de les utiliser. Poursuivant l'exemple ci-dessus, il vous faudrait utiliser la fonction de la Toolbox appelée GetMBarHeight. Et c'est tout !

hauteur% = FN GetMBarHeight

Pour le moment, il vous faudra consulter la documentation d'Apple pour connaître l'ensemble des fonctions disponibles pour accéder à ces valeurs globales.


[haut de la page]

Structures opaques

De manière générale, tout ce qui appartient au système est maintenant protégé. Ceci reste vrai pour bon nombre de choses qui sont tenues pour bien connues et largement utilisées par les programmeurs sur Macintosh. Plus précisément des structures très communes comme celles qui définissent les fenêtres, menus, contrôles, etc. sont devenues 'opaques' dans Carbon.
La terminologie*, quant à elle, ne nous cache rien : le programmeur ne doit rien assumer en ce qui concerne l'organisation interne de ces structures. En conséquence, les anciennes techniques de programmation qui les manipulent sont vouées à l'échec :

  • Accès aux valeurs à l'aide de décalages en mémoire (fréquemment réalisé via des pseudo-records);

  • Lecture/Ecriture des champs de vrais records.

Ces deux techniques présupposent un arrangement interne bien précis des structures impliquées, aussi, sont elles bonnes pour un crash dans Carbon.

Là encore, Apple nous fournit la solution : des fonctions accesseurs appelées du terme générique getter et setter ont été mises à notre disposition. Ainsi, une bonne partie de votre travail de conversion consistera à trouver la fonction adéquate qui viendra en remplacement de votre ancien code.

Exemple :

Auparavant, pour retrouver le titre d'un menu donné, nous pouvions :

  • utiliser la constante prédéfinie _menuData comme un décalage pour récupérer la chaîne Pascal localisée dans le handle du menu, comme montré ci-dessous par exemple :

    titre$ = PSTR$([menuHandle] + _menuData)

  • ou bien, définir un record MenuInfo déclaré dans les headers d'Apple comme suit :

    BEGIN RECORD MenuInfo
      DIM menuID      AS SHORT
      DIM menuWidth   AS SHORT
      DIM menuHeight  AS SHORT
      DIM menuProc    AS HANDLE
      DIM enableFlags AS LONG
      DIM menuData    AS STR255
    END RECORD

    Par la suite, après avoir déclaré notre menuHandle comme un handle pointant sur une structure MenuInfo (DIM menuHandle AS HANDLE TO MenuInfo) nous aurions pu écrire ceci :

    titre$ = menuHandle..menuData

    Les techniques ci-dessus continuent à fonctionner en PPC et 68K, mais pas dans Carbon, où l'on doit utiliser la fonction accesseur de la Toolbox GetMenuTitle :

    bidon& = FN GetMenuTitle(menuRef,titre$)

    Notez deux choses intéressantes ici : Mis à part le fait qu'une telle fonction n'existait pas avant Carbon, la référence menuRef peut être obtenue avec la fonction régulière GetMenuHandle qui peut être également utilisée pour retourner un menuHandle en PPC et 68K. De plus, cette fonction a une particularité dans le sens où elle retourne à la fois le titre du menu dans la variable titre$ passée en paramètre, aussi bien qu'un pointeur sur la chaîne de caractères du titre en tant que résultat de la fonction. Ceci vous permet de passer directement le résultat retourné en tant que paramètre à une autre fonction.

    De même une instruction telle que menuHandle..menuWidth% doit être remplacée par FN GetMenuWidth(menuHandle), et ainsi de suite...

    * Vous remarquerez que ces structures sont définies dans les headers universels d'Apple en tant que pointeurs génériques ou handles génériques. Habituellement, leur nom se termine par le suffixe ref. Par exemple, nous avons pris l'habitude de travailler avec des ControlHandles qui sont des handles pointant sur une structure ControlRecord (^^ControlRecord), dans Carbon, on doit maintenant traiter des ControlRefs qui sont de simples handles non typés. Une énorme partie de la Toolbox a été portée dans CarbonLib de telle sorte que ces changements subtils sont gérés presque de manière transparente (cool pour des structures opaques !) et que beaucoup d'appels Toolbox continueront à fonctionner sans modifications de votre code.


  • [haut de la page]

    X- Files

    Normalement, sans le travail acharné de Staz Software, ce terrain glissant aurait dû devenir le vrai cauchemar pour les programmeurs FutureBASIC. L'essentiel des fonctions de FutureBASIC relatives à la gestion des fichiers reposaient sur l'obsolète numéro de référence de répertoire de travail (working directory reference number). Vous le croirez ou pas, cette référence maintenant totalement abandonnée par Apple, continue à fonctionner dans Carbon avec FutureBASIC !

    En réalité, Staz Software a ressuscité cette entité qui depuis longtemps nous rend bien des services. Mais ici, tout est fait dans les coulisses, et si vous avez pris l'habitude de gérer l'ouverture, la lecture et l'écriture de vos fichiers à travers les commandes intégrées de FutureBASIC, vous ne noterez aucune différence. C'est vraiment très surprenant !

    Les problèmes vont commencer à surgir, si vous avez utilisé les numéros de répertoire de travail gérés maintenant par FutureBASIC avec des appels Toolbox...

    C'est souvent le cas lorsqu'on remplit un bloc de paramètres pour l'envoyer à une fonction de la Toolbox. Naturellement, il y a des solutions. Tout d'abord, la plus simple est d'appeler une fonction intégrée du runtime qui s'occupera de la conversion nécessaire avant l'expédition du bloc de paramètres à la Toolbox :

    #IF CarbonLib
      FN FBWDToPBWD(blocParametres)
    #ENDIF

    Bien évidemment, vous devez aussi vous assurer que l'appel Toolbox que vous voulez utiliser juste après est toujours présent dans Carbon (un certain nombre n'ont pas survécu au voyage).

    Dans d'autres circonstances, vous tirerez un meilleur parti de l'utilisation de la respectable et plus recommandée structure File Spec. Cela demandera plus de modifications dans votre code, mais la Release 6 introduit le record FSSpec dans beaucoup de ces fonctions de fichier (les boîtes de dialogue standard pour les fichiers savent maintenant retourner une telle structure, que vous pouvez ensuite utiliser dans la commande OPEN).

    Non seulement vous avez à votre disposition ces deux possibilités, mais la Release 6 arrive aussi avec une quantité de nouvelles routines utilisateur qui vous permettent de gérer des tâches telles que vérifier l'existence d'un fichier, copier et déplacer des fichiers et même passer en revue le contenu d'un dossier entier. Et tout cela fonctionne du 68K à Carbon de manière totalement transparente.

    Au bout du compte, vous serez largement assisté dans votre travail de conversion.


    [haut de la page]

    Presse-Papiers

    La gestion du Presse-Papiers est quelque peu différente dans Carbon. Mais si vous savez copier et coller, vous allez vous en tirer sans problèmes. Avec la plupart de vos programmes, vous n'aurez qu'à ouvrir l'un des petits fichiers d'exemple sur le CD de FB^3, copiez les fonctions adéquates et enfin les insérer dans votre code.


    [haut de la page]

    Procédures de rappel (Callback Procedures)

    Si vous êtes un accroc des procédures de rappel, vous allez avoir un peu de travail à fournir. Mais, honnêtement, pas tant que cela ! L'installation d'une procédure de rappel dans Carbon nécessite l'utilisation de la fonction Toolbox appropriée au travail à réaliser. De plus, le point d'entrée correct de la procédure doit être "calculé".
    Vous pourriez avoir à déclarer la fonction d'installation parce que toutes ne sont pas définies dans les headers de FutureBASIC. Comme elles sont toutes conçues sur le même modèle, le processus est très simple. Prenons l'exemple d'un filtre de dialogue ou d'alerte.

    Pour installer un filtre dans un dialogue ou une alerte, vous avez besoin de la fonction Toolbox NewModalFilterUPP. Vous pouvez déclarer cette fonction de la façon suivante :

    #IF CarbonLib
      TOOLBOX FN NewModalFilterUPP(PTR)=PTR
    #ENDIF

    Lorsqu'il est temps dans votre programme d'installer la procédure, tout ce que vous avez à faire est de vérifier si vous compilez pour Carbon, puis d'envoyer à la fonction d'installation le point d'entrée correcte de votre procédure. Cela pourrait être fait comme suit :

    DIM myProc AS PROC

    myProc = PROC "ma procédure filtre"

    #IF CarbonLib
      myProc = FN NewModalFilterUPP( [myProc + ¬ _FBprocToProcPtrOffset] )
    #ENDIF

    choix = FN Alert(resID,myProc)

    Comme précédemment indiqué, ce schème s'applique à toutes les procédures de rappel, aussi et en bref, le seul vrai truc pour vous est de trouver la fonction d'installation de la Toolbox appropriée à vos besoins.


    [haut de la page]

    Mises à jour de l'écran

    Maintenant que votre programme compile sans erreurs, vous êtes prêt à expérimenter d'étranges comportements. Il est possible que votre programme souffre d'une lenteur inattendue ou d'échecs répétés dans la mise à jour de l'écran sous OS X. Bienvenue dans le monde des fenêtres bufférisées

    Dans OS X, les commandes d'affichage ou de dessin dirigées dans une fenêtre donnée sont stockées temporairement dans une mémoire tampon, laquelle est vidée par le Système aussitôt que la fonction Toolbox WaitNextEvent est invoquée. Cela signifie qu'afin de voir une mise à jour effective de l'écran, votre application doit appeler HANDLEEVENTS.
    Ceci n'est pas toujours possible, par exemple, lorsque le flux de votre programme est piégé dans une boucle qui a besoin de rafraîchir la fenêtre d'affichage. Pour cette raison, la Release 6 arrive avec un nouveau mot-clé qui vous permet de forcer le système à vider la mémoire tampon en attente.

    Sous OS X, FLUSHWINDOWBUFFER mettra l'écran à jour immédiatement, mais cela ne va pas sans un effet secondaire et, malgré tout, vous noterez très certainement un ralentissement de votre application.

    Bien que la commande FLUSHWINDOWBUFFER soit inopérante et sans danger avec tout autre version du système, vous pourriez avoir besoin de développer une stratégie différente concernant la mise à jour de l'écran dans vos programmes sous OS X.
    À cet effet, vous trouverez la démo appelée "Vitesse d'affichage dans OS X", localisée dans le dossier "Dons", particulièrement intéressante. Ce très petit exemple, écrit par Robert Purves, chronomètre cinq techniques différentes pour l'affichage. Essayez d'adapter celle qui répond le mieux à vos besoins.
    Peut-être est-ce aussi là l'occasion de revisiter votre code :
    Utilisez-vous correctement les registres du PPC (ne passez pas à côté des registres pour les flottants non plus)?
    Déclenchez-vous des commandes d'affichage inutiles (exécuter un calcul anticipé est de loin plus rapide et plus facile pour le processeur que d'exécuter des commandes de dessins)?

    Examinez les autres exemples sur le CD qui ont trait à la vitesse d'exécution, vous y glanerez quantité d'informations très utiles.
    Testez vos fonctions avec le Profileur, vous pourriez être surpris du gain de vitesse obtenu par de simples changements dans votre code. Chaque petite pierre de cet édifice peut aider votre application à paraître plus fluide dans OS X.

    Sur ce même front des mises à jour, vous devez savoir que les procédures InvalRect et ValidRect ont disparu de la Toolbox avec Carbon. Toujours prête à aider, la Release 6 vous procure deux fonctions intégrées au runtime qui vous simplifieront le processus de conversion. En fait, la modification de votre code devrait être un jeu d'enfant, vous n'avez qu'à remplacer le mot-clé CALL (optionnel) par FN et tout continuera à fonctionner comme auparavant :

    Changez :
    CALL InvalRect(r) // ou simplement InvalRect(r)
    par :
    FN InvalRect(r)


    [haut de la page]

    GrafPorts

    Avant Carbon, on pouvait considérer un GrafPort comme une structure imbriquée dans la définition d'un CWindowRecord (record de fenêtre). Comme le record GrafPort était le premier champ du record de la fenêtre, les deux structures étaient confondues en mémoire. Aussi pouvions-nous utiliser un pointeur de fenêtre indifféremment pour référencer le GrafPort de la fenêtre ou la structure entière du record de fenêtre.

    Les instructions suivantes pouvaient fonctionner :

    GET WINDOW wndNum%,wndPtr&
    CALL SetPort(wndPtr&)


    Ceci est interdit dans Carbon, mais peut-être aimeriez-vous faire un petit tour du côté de CrashTown à partir du moment où c'est gratuit. Les pointeurs de fenêtres et les GrafPorts de fenêtres sont maintenant des entités séparées. Vous aurez probablement à vérifier toutes les parties de votre code qui traitent les ports graphiques pour vous assurer que des GrafPorts réels sont passés aux fonctions et procédures de la Toolbox.

    Remarquez que la Release 6 peut vous aider ici aussi avec la fonction WINDOW qui, à l'aide de deux nouvelles constantes, a été améliorée pour retourner un CGrafPort ou la WindowRef de la fenêtre d'affichage.

    WINDOW(_wndRef) retournera un pointeur sur la référence (opaque) de la fenêtre, tandis que WINDOW(_wndPort) retournera un pointeur sur le GrafPort de la fenêtre.


    [haut de la page]

    Déverminage

    Dans OS X, l'allocation mémoire de votre application n'est plus de votre ressort. Ceci est géré par le système.
    OK, c'est une bonne chose, spécialement pour l'utilisateur final. Toutefois, pour vous, en tant que programmeur, il devient plus difficile de traquer les fuites de mémoire dans vos programmes. Vos outils habituels ne vous seront pas d'un grand secours dans OS X, à moins que vous ne forciez vos programmes carbonisés à s'exécuter dans l'environnement Classic en ajoutant simplement l'instruction suivante dans votre code:

    KILL RESOURCES "plst",0

    De cette manière, les fuites de mémoires seront beaucoup plus facilement et rapidement découvertes qu'avec OS X où elles peuvent rester indétectables. Bien entendu, vous supprimerez cette instruction au moment de construire votre application finale.


    [haut de la page]

    Si vous rencontrez d'autres problèmes dans le portage de votre code, n'hésitez pas à nous contacter, d'autres ont dû certainement faire face à la même situation et nous complèteront la liste des choses à vérifier.

    D'ici là, passez un excellent moment à programmer avec la Release 6.

      © 2000 Pix&Mix  
      Tous droits réservés
    INFO  |  ACQUÉRIR |  PLAN  |  RESSOURCES

      FutureBASIC est une marque déposée appartenant à Staz Software, Inc et utilisée avec permission.