Obligement - L'Amiga au maximum

Jeudi 21 septembre 2017 - 18:02  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Hit Parade
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles in other languages


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Moteurs de recherche
 · Pages de liens
 · Constructeurs matériels
 · Matériel
 · Autres sites de matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Développeurs logiciels
 · Logiciels
 · Développeurs de jeux
 · Jeux
 · Autres sites de jeux
 · Scène démo
 · Divers
 · Informatique générale


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : C - création d'une classe BOOPSI
(Article écrit par Eric Totel et extrait d'Amiga News - mars 1996)


Pour illustrer le précédent article, nous allons réaliser cette fois une classe BOOPSI élémentaire. Son but est uniquement éducatif. En effet, peu de personnes pourront, à mon avis, en trouver une utilisation pratique, sauf peut-être des gens ayant besoin d'une gestion dynamique des chaînes (ce qui peut d'ailleurs être réalisé sans utiliser BOOPSI !).

Notre classe comporte la définition d'une méthode (outre les méthodes fondamentales) STM_Concat (concaténation de notre chaîne et d'une chaîne de caractère C classique) et d'un attribut STA_Content (contenu de notre chaîne) qui peut être défini à l'initialisation, lu (GetAttr), et écrit (SetAttr). L'application de la méthode STM_Concat modifie également l'attribut STA_Content. Notre classe effectue systématiquement une copie des chaînes qu'on lui passe.

Les éléments à retenir dans cet exemple sont sans aucun doute :
  • La création d'une classe publique (InitStringClass). Vous noterez que dans notre exemple, le fait que la classe soit publique est inutile : une classe privée aurait parfaitement fait l'affaire.
  • La destruction d'une classe publique (DisposeStringClass).
  • Le positionnement des attributs : utilisation de la fonction SetAttrs qui correspond à un envoi de la méthode OM_SET et à l'exécution de la fonction mSetString.
  • La lecture d'un attribut : utilisation de GetAttr, c'est-à-dire envoi de la méthode OM_GET et exécution de mGetString.
  • On utilise une structure dont la première composante est un ULONG (la méthode reçue par l'objet) pour passer des paramètres précis à une méthode que l'on crée (ici mConcatString, et la structure utilisée est pConcatString).
  • DoSuperMethodA et DoSuperMethod permettent de propager la méthode reçue à la superclasse (classe parente).
  • Amusez-vous à ajouter quelques méthodes (comme par exemple concaténer deux objets BOOPSI String) pour comprendre le fonctionnement de l'ensemble. Une fois le mécanisme compris, vous disposerez d'un moteur objet extrêmement puissant que vous pourrez programmer en C.
#include <dos/dos.h>
#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/utility_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/utility_pragmas.h>

#include <exec/memory.h>

#include <stdio.h>
#include <string.h>

#if defined(_DCC)
#define REG(x) __ ## x
#define SAVEDS __geta4
#define ASM
#define REGARGS __regargs
#else
#if defined(__SASC)
#define REG(x) register __ ## x
#define SAVEDS __saveds
#define ASM __asm                               
#define REGARGS __regargs                       
#endif                                          
#endif 

/* Données de la classe */
struct StringData
{
  char *string;
};

/* Paramètre de la méthode Concat */
struct pConcatString
{
  ULONG Method;
  char  *string;
};

/* Bibliothèques utilisées */
struct Library *IntuitionBase;
struct Library *UtilityBase;

/* Définition des attributs et Méthodes */
/* Attributs */
#define STA_Content (TAG_USER + 0)
/* Méthodes  */
#define STM_Concat  (TAG_USER + 10)

struct IClass   *StringClass;

/**********************************/
/* Définition de la classe String */
/**********************************/

/*******************************************/
/* Positionnement des attributs de l'objet */
/*******************************************/
SAVEDS ULONG mSetString(Class *cl, Object *obj, struct opSet * msg)
{
  struct StringData *data = INST_DATA(cl, obj);
  struct TagItem *ti, *tstate;
  ULONG  retval = 0;
  ULONG  size;

  retval = DoSuperMethodA(cl, obj, (Msg)msg);
  ti = msg->ops_AttrList;
  tstate = ti;
  while(ti = NextTagItem(&tstate))
  {
    switch(ti->ti_Tag)
    {
    case STA_Content:
      if (data->string) FreeVec(data->string);
      size = strlen((char*)ti->ti_Data);
      if (data->string = AllocVec(size+1, MEMF_PUBLIC|MEMF_CLEAR))
        {
          memcpy(data->string, (char*)ti->ti_Data, size+1);
        }
      retval = 1L;
      break;
    }
  }
  return(retval);
}

/************************************/
/* Lecture des attributs de l'objet */
/************************************/
SAVEDS ULONG mGetString(Class *cl, Object *obj, struct opGet * msg)
{
  struct StringData *data = INST_DATA(cl, obj);
  ULONG   retval = 0;

  switch(msg->opg_AttrID)
    {
    case STA_Content:
      *(msg->opg_Storage) = (ULONG) data->string;
      retval = 1;
      break;
    }

  if (!retval) DoSuperMethodA(cl, obj, (Msg)msg);

  return(retval);
}

/******************************/
/* Création d'un nouvel objet */
/******************************/
SAVEDS ULONG mNewString(Class *cl, Object *obj, struct opSet *msg)
{
  struct StringData *data = NULL;
  ULONG retval = 0;
  char *straux;
  ULONG size;

  if (retval = DoSuperMethodA(cl, obj, (Msg)msg))
    {
      data = INST_DATA(cl, retval);
      if (data->string = (char*) GetTagData(STA_Content, 0, msg->ops_AttrList))
        {
          if (straux = AllocVec((size = strlen(data->string))+1, MEMF_PUBLIC|MEMF_CLEAR))
            {
              memcpy(straux, data->string, size+1);
              data->string = straux;
            }
        }
    }
  return((ULONG)retval);
}

/**************************/
/* Destruction d'un objet */
/**************************/
ULONG mDisposeString(Class *cl, Object *obj, Msg msg)
{
  struct StringData *data = INST_DATA(cl, obj);

  if (data->string) FreeVec(data->string);

  return(DoSuperMethodA(cl, obj, msg));
}

/****************************************************/
/* Concatenation d'une string et d'une chaine char* */
/****************************************************/
SAVEDS ULONG mConcatString(Class *cl, Object *obj, struct pConcatString *msg)
{
  struct StringData *data = INST_DATA(cl, obj);
  char   *straux;
  ULONG  size;

  straux = data->string;
  if (msg->string)
    {
      if ((straux)&&
      (data->string = AllocVec(strlen(msg->string)+strlen(straux)+1, MEMF_PUBLIC|MEMF_CLEAR)))
    {
      sprintf(data->string, "%s%s", straux, msg->string);
      FreeVec(straux);
    }
      else
        {
          SetAttrs(obj, STA_Content, msg->string, TAG_DONE);
        }
    }

  return(0);
}

/***********************************************************/
/* Fonction Dispatcher : reçoit les méthodes et les traite */
/***********************************************************/
SAVEDS ULONG DispatcherString(struct IClass *cl, Object *obj, Msg msg)
{
  APTR retval = NULL;

  /* On appelle la méthode désirée */
  switch(msg->MethodID)
  {
  case OM_NEW:     return(mNewString(cl, obj, (struct opSet *)msg));
  case OM_SET:     return(mSetString(cl, obj, (struct opSet *)msg));
  case OM_GET:     return(mGetString(cl, obj, (struct opGet *)msg));
  case OM_DISPOSE: return(mDisposeString(cl, obj, msg));
  case STM_Concat: return(mConcatString(cl, obj, (struct pConcatString *)msg));
  default:
    retval = (APTR)DoSuperMethodA(cl, obj, msg);
    break;
  }

  return((ULONG)retval);
}

/*******************************/
/* Initialisation de la classe */
/*******************************/
BOOL InitStringClass(void)
{
  extern ULONG HookEntry();
  BOOL   retval = FALSE;

  /* Creation de la classe */
  if (StringClass = MakeClass("StringClass", "modelclass", NULL, sizeof(struct StringData), 0))
    {
      StringClass->cl_Dispatcher.h_Entry = HookEntry;
      StringClass->cl_Dispatcher.h_SubEntry = DispatcherString;
      /* On rend la classe publique (pas nécessaire dans notre cas) */
      AddClass(StringClass);
      retval = TRUE;
    }

  return(retval);
}

/****************************/
/* Destruction de la classe */
/****************************/
void DisposeStringClass(void)
{
  /* On enleve la classe du système (seulement si elle est publique) */
  RemoveClass(StringClass);
  /* On libère la classe */
  FreeClass(StringClass);
}

/*******************************/
/* Fermeture des bibliothèques */
/*******************************/
void Clean(void)
{
  if (IntuitionBase) CloseLibrary(IntuitionBase);
  if (UtilityBase) CloseLibrary(UtilityBase);
}

/************************************/
/* Fonction principale du programme */
/*     Test de la classe String     */
/************************************/
int main(void)
{
  APTR MyString;
  char *straux;

  /* Initialisations des bibliothèques */
  if (!(IntuitionBase = OpenLibrary("intuition.library", 0)))
    {
      Clean();
      return(20);
    }
  if (!(UtilityBase = OpenLibrary("utility.library", 0)))
    {
      Clean();
      return(20);
    }

  /* Initialisation de la classe boopsi */
  if (!InitStringClass())
    {
      Clean();
      return(20);
    }

  /* Test de l'objet */
  if (MyString = NewObject(NULL, "StringClass",
                           STA_Content, "Essai",
                           TAG_DONE))
    {
      /* Test du get */
      GetAttr(STA_Content, MyString, (ULONG*)&straux);
      printf ("Actuellement MyString = %s\n", straux);

      /* Test du set */
      SetAttrs(MyString, STA_Content, "Essai2", TAG_DONE);
      GetAttr (STA_Content, MyString, (ULONG*)&straux);
      printf  ("Actuellement MyString = %s\n", straux);

      /* Test du STM_Concat */
      DoMethod(MyString, STM_Concat, " - Juste pour tester");
      GetAttr (STA_Content, MyString, (ULONG*)&straux);
      printf  ("Actuellement MyString = %s\n", straux);

      /* Effacement de l'objet */
      DisposeObject(MyString);
    }

  /* Détruit la classe string */
  DisposeStringClass();
  Clean();

  return(0);
}


[Retour en haut] / [Retour aux articles] [Article précédent]