Obligement - L'Amiga au maximum

Vendredi 19 avril 2024 - 12:41  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

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

Articles in english


Réseaux sociaux

Suivez-nous sur X




Liste des 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,
ALL


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


Galeries

Menu des galeries

BD d'Amiga Spécial
Caricatures Dudai
Caricatures Jet d'ail
Diagrammes de Jay Miner
Images insolites
Fin de jeux (de A à E)
Fin de Jeux (de F à O)
Fin de jeux (de P à Z)
Galerie de Mike Dafunk
Logos d'Obligement
Pubs pour matériels
Systèmes d'exploitation
Trombinoscope Alchimie 7
Vidéos


Téléchargement

Documents
Jeux
Logiciels
Magazines
Divers


Liens

Associations
Jeux
Logiciels
Matériel
Magazines et médias
Pages personnelles
Réparateurs
Revendeurs
Scène démo
Sites de téléchargement
Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec


A Propos

A propos d'Obligement

A Propos


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 (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]