Gestion des objets (+ exemple)

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Gestion des objets (+ exemple)

Message par Dr. Dri »

Ce code permet d'utiliser les fonctions internes de PB pour gérer des listes d'objets. C'est pratique pour ceux qui font des userlibs, il suffit d'initialiser une liste d'objets et on peut y créer des objets statiques ou dynamiques (avec #PB_Any)
  • Liste des fonctions:
  • Object_GetOrAllocate(*Objects, Object.l)
  • Object_GetObject(*Objects, Object.l)
  • Object_IsObject(*Objects, Object.l)
  • Object_EnumerateAll(*Objects, EnumerateCallback, *VoidData)
  • Object_EnumerateStart(*Objects)
  • Object_EnumerateNext(*Objects, *ID.Long)
  • Object_EnumerateAbort(*Objects)
  • Object_Free(*Objects, Object.l)
  • Object_Init(StructureSize.l, IncrementStep.l, FreeObjectFunction)
  • Object_GetThreadMemory(MemoryID.l)
  • Object_InitThreadMemory(Size.l, InitFunction, EndFunction)
Il suffit d'inclure ce fichier pour avoir accès aux fonctions

Code : Tout sélectionner

Prototype   ThreadFunction(Param)

Prototype.l ObjectEnumerateAllCallback(Object.l, *Element, *VoidData)
Prototype   ObjectFreeFunction(Object.l)

Structure PB_SimpleList
  *Next    .PB_SimpleList
  *Previous.PB_SimpleList
EndStructure

Structure PB_Object
  StructureSize.l
  IncrementStep.l
  ObjectsNumber.l
  *ListFirstElement.PB_SimpleList

  FreeObject.ObjectFreeFunction

  Current.l
  *CurrentElement.PB_SimpleList

CompilerIf #PB_Compiler_Thread
  IncrementShift.l
  *FirstObjectsArea.PB_SimpleList
  *LastObjectsArea .PB_SimpleList
  ObjectMutex.Critical_Section
CompilerElse
  *ObjectsArea
CompilerEndIf
  
EndStructure

Prototype   PB_Object_GetOrAllocate   (*Object.PB_Object, Object.l)
Prototype   PB_Object_GetObject       (*Object.PB_Object, Object.l)
Prototype   PB_Object_IsObject        (*Object.PB_Object, Object.l)
Prototype   PB_Object_EnumerateAll    (*Object.PB_Object, Callback.ObjectEnumerateAllCallback, *VoidData)
Prototype   PB_Object_EnumerateStart  (*Object.PB_Object)
Prototype   PB_Object_EnumerateNext   (*Object.PB_Object, *ID.Long)
Prototype   PB_Object_EnumerateAbort  (*Object.PB_Object)
Prototype   PB_Object_Free            (*Object.PB_Object, Object.l)
Prototype.l PB_Object_Init            (StructureSize.l, IncrementStep.l, FreeObject.ObjectFreeFunction)
Prototype   PB_Object_GetThreadMemory (MemoryID.l)
Prototype.l PB_Object_InitThreadMemory(Size.l, InitFunction.ThreadFunction, EndFunction.ThreadFunction)

Global Object_GetOrAllocate   .PB_Object_GetOrAllocate
Global Object_GetObject       .PB_Object_GetObject
Global Object_IsObject        .PB_Object_IsObject
Global Object_EnumerateAll    .PB_Object_EnumerateAll
Global Object_EnumerateStart  .PB_Object_EnumerateStart
Global Object_EnumerateNext   .PB_Object_EnumerateNext
Global Object_EnumerateAbort  .PB_Object_EnumerateAbort
Global Object_Free            .PB_Object_Free
Global Object_Init            .PB_Object_Init
Global Object_GetThreadMemory .PB_Object_GetThreadMemory
Global Object_InitThreadMemory.PB_Object_InitThreadMemory

!extrn _PB_Object_GetOrAllocateID@8
!extrn _PB_Object_GetObject@8
!extrn _PB_Object_IsObject@8
!extrn _PB_Object_EnumerateAll@12
!extrn _PB_Object_EnumerateStart@4
!extrn _PB_Object_EnumerateNext@8
!extrn _PB_Object_EnumerateAbort@4
!extrn _PB_Object_FreeID@8
!extrn _PB_Object_Init@12
!extrn _PB_Object_GetThreadMemory@4
!extrn _PB_Object_InitThreadMemory@12

!MOV [v_Object_GetOrAllocate]   , _PB_Object_GetOrAllocateID@8
!MOV [v_Object_GetObject]       , _PB_Object_GetObject@8
!MOV [v_Object_IsObject]        , _PB_Object_IsObject@8
!MOV [v_Object_EnumerateAll]    , _PB_Object_EnumerateAll@12
!MOV [v_Object_EnumerateStart]  , _PB_Object_EnumerateStart@4
!MOV [v_Object_EnumerateNext]   , _PB_Object_EnumerateNext@8
!MOV [v_Object_EnumerateAbort]  , _PB_Object_EnumerateAbort@4
!MOV [v_Object_Free]            , _PB_Object_FreeID@8
!MOV [v_Object_Init]            , _PB_Object_Init@12
!MOV [v_Object_GetThreadMemory] , _PB_Object_GetThreadMemory@4
!MOV [v_Object_InitThreadMemory], _PB_Object_InitThreadMemory@12
Un exemple d'utilisation, en espérant que ca aide...

Code : Tout sélectionner

IncludeFile "Object.pbi"

;la structure qui contient les
;informations sur les timers
Structure Timer
  Event.l
  Window.l
  Elapse.l
EndStructure

;il faut que ce soit global ^^
;ou alors shared dans chaque fonction
Global TimerObjects

;la fonction la plus importante, sans elle
;pas d'objets statiques/dynamiques
Procedure.l FreeTimer(Timer.l)
  Protected Free.l = #False, *Timer.Timer
  
  If Timer <> #PB_Any And Object_IsObject(TimerObjects, Timer)
    *Timer = Object_GetObject(TimerObjects, Timer)
  EndIf
  
  If *Timer And IsWindow(*Timer\Window)
    Free = KillTimer_(WindowID(*Timer\Window), *Timer\Event)
    Object_Free(TimerObjects, Timer)
  EndIf
  
  ProcedureReturn Free
EndProcedure

;Retourne "non-zero" si le timer a été créé
;Retourne l'index du timer si Timer = #PB_Any
Procedure.l CreateTimer(Timer.l, Window.l, Event.l, Elapse.l)
  Protected Create.l = #Null, *Timer.Timer
  
  If IsWindow(Window) And Event
    FreeTimer(Timer)
    *Timer = Object_GetOrAllocate(TimerObjects, Timer)
  EndIf
  
  If *Timer
    SetTimer_(WindowID(Window), Event, Elapse, #Null)
    *Timer\Event  = Event
    *Timer\Window = Window
    *Timer\Elapse = Elapse
  EndIf
  
  If Timer = #PB_Any
    Create = *Timer
  ElseIf *Timer
    Create = *Timer\Event
  EndIf
  
  ProcedureReturn Create
EndProcedure

;trois fonctions pour meubler
Procedure.l GetTimerEvent(Timer.l)
  Protected Event.l = #PB_Any, *Timer.Timer
  
  *Timer = Object_GetObject(TimerObjects, Timer)
   
  If *Timer And IsWindow(*Timer\Window)
    Event = *Timer\Event
  EndIf
  
  ProcedureReturn Event
EndProcedure

Procedure.l GetTimerWindow(Timer.l)
  Protected Window.l = #PB_Any, *Timer.Timer
  
  *Timer = Object_GetObject(TimerObjects, Timer)
   
  If *Timer And IsWindow(*Timer\Window)
    Window = *Timer\Window
  EndIf
  
  ProcedureReturn Window
EndProcedure

Procedure.l GetTimerElapse(Timer.l)
  Protected Elapse.l = #PB_Any, *Timer.Timer
  
  *Timer = Object_GetObject(TimerObjects, Timer)
   
  If *Timer And IsWindow(*Timer\Window)
    Elapse = *Timer\Elapse
  EndIf
  
  ProcedureReturn Elapse
EndProcedure

;si on fait une lib autant
;créer les évennements qui vont avec ^^
#PB_Event_Timer = #WM_TIMER

;retourne le numéro de timer (#PB_Any s'il n'existe pas)
Procedure.l EventTimer()
  Protected Window.l, Event.l, Temp.l
  Protected Timer.l = #PB_Any, *Timer.Timer
  
  Window = EventWindow()
  Event  = EventwParam()
  
  Object_EnumerateStart(TimerObjects)
  
  While Object_EnumerateNext(TimerObjects, @Temp)
    *Timer = Object_GetObject(TimerObjects, Temp)
    
    If *Timer\Window = Window And *Timer\Event = Event
      Object_EnumerateAbort(TimerObjects)
      Timer = Temp
    EndIf
  Wend
  
  ProcedureReturn Timer
EndProcedure

;crée la liste d'objets des timers,
;je ne sais pas à quoi correspond le 2e argument
TimerObjects = Object_Init(SizeOf(Timer), 1, @FreeTimer())

;fin de la "lib"

;-------------------------------------------------------------------------------

;début du programme

Enumeration
  #Timer_A
  #Timer_C
EndEnumeration

If OpenWindow(0, 0, 0, 222, 50, "Timer", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CreateGadgetList(WindowID(0))
  
  ButtonGadget(0, 10, 10, 200, 30, "Timer", #PB_Button_Toggle)
  
  CreateTimer(#Timer_A, 0, 6, 2000)
  CreateTimer(#Timer_C, 0, 2, 1500)
  
  Repeat
    
    Event = WaitWindowEvent()
    
    If Event = #PB_Event_Gadget
      
      If GetGadgetState(0)
        Timer = CreateTimer(#PB_Any, 0, 1, 1000)
      Else
        FreeTimer(Timer)
      EndIf
      
    ElseIf Event = #PB_Event_Timer
      
      Select EventTimer()
        Case #Timer_A
          Debug "#Timer_A"
          
        Case #Timer_C
          Debug "#Timer_C"
          
        Case Timer
          Debug "Timer"
          
      EndSelect
      
    EndIf
    
  Until Event = #PB_Event_CloseWindow
EndIf
Dri ;)
Dernière modification par Dr. Dri le mer. 21/juin/2006 16:51, modifié 1 fois.
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

intéressant Dr Dri, va falloir déchiffrer tout çà mais merci.
je pense que çà va me servir justement pour le projet #1 (SQL).
:P
Image
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Une version light, j'ai gardé l'essentiel

Code : Tout sélectionner

Prototype   PB_Object_GetOrAllocate   (Objects, Object.l)
Prototype   PB_Object_GetObject       (Objects, Object.l)
Prototype   PB_Object_IsObject        (Objects, Object.l)
Prototype   PB_Object_EnumerateAll    (Objects, ObjectEnumerateAllCallback, *VoidData)
Prototype   PB_Object_EnumerateStart  (Objects)
Prototype   PB_Object_EnumerateNext   (Objects, *Object.Long)
Prototype   PB_Object_EnumerateAbort  (Objects)
Prototype   PB_Object_Free            (Objects, Object.l)
Prototype.l PB_Object_Init            (StructureSize.l, IncrementStep.l, ObjectFreeFunction)
Prototype   PB_Object_GetThreadMemory (MemoryID.l)
Prototype.l PB_Object_InitThreadMemory(Size.l, InitFunction, EndFunction)

Global Object_GetOrAllocate   .PB_Object_GetOrAllocate
Global Object_GetObject       .PB_Object_GetObject
Global Object_IsObject        .PB_Object_IsObject
Global Object_EnumerateAll    .PB_Object_EnumerateAll
Global Object_EnumerateStart  .PB_Object_EnumerateStart
Global Object_EnumerateNext   .PB_Object_EnumerateNext
Global Object_EnumerateAbort  .PB_Object_EnumerateAbort
Global Object_Free            .PB_Object_Free
Global Object_Init            .PB_Object_Init
Global Object_GetThreadMemory .PB_Object_GetThreadMemory
Global Object_InitThreadMemory.PB_Object_InitThreadMemory

!extrn _PB_Object_GetOrAllocateID@8
!extrn _PB_Object_GetObject@8
!extrn _PB_Object_IsObject@8
!extrn _PB_Object_EnumerateAll@12
!extrn _PB_Object_EnumerateStart@4
!extrn _PB_Object_EnumerateNext@8
!extrn _PB_Object_EnumerateAbort@4
!extrn _PB_Object_FreeID@8
!extrn _PB_Object_Init@12
!extrn _PB_Object_GetThreadMemory@4
!extrn _PB_Object_InitThreadMemory@12

!MOV [v_Object_GetOrAllocate]   , _PB_Object_GetOrAllocateID@8
!MOV [v_Object_GetObject]       , _PB_Object_GetObject@8
!MOV [v_Object_IsObject]        , _PB_Object_IsObject@8
!MOV [v_Object_EnumerateAll]    , _PB_Object_EnumerateAll@12
!MOV [v_Object_EnumerateStart]  , _PB_Object_EnumerateStart@4
!MOV [v_Object_EnumerateNext]   , _PB_Object_EnumerateNext@8
!MOV [v_Object_EnumerateAbort]  , _PB_Object_EnumerateAbort@4
!MOV [v_Object_Free]            , _PB_Object_FreeID@8
!MOV [v_Object_Init]            , _PB_Object_Init@12
!MOV [v_Object_GetThreadMemory] , _PB_Object_GetThreadMemory@4
!MOV [v_Object_InitThreadMemory], _PB_Object_InitThreadMemory@12
Dri
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

merci c'est cool.

tu sais pas pourquoi çà marche pas dans jaPBe par hasard ?

Compilateur:
POLINK: fatal error: 11 unresolved external(s)
Image
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Franchement je n'en sais rien, comme ce sont les symboles externes (en gros les adresses des fonctions) peut être qu'avec jaPBe il faut virer les arguments (en gros vire tous les @ et ce qui va apres)

Dri :-?
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

pas çà, je vais demander à gnozal.
Image
gnozal
Messages : 832
Inscription : mar. 07/déc./2004 17:35
Localisation : France
Contact :

Message par gnozal »

Flype a écrit :pas çà, je vais demander à gnozal.
C'est un bug Purebasic.
Si je fais la même chose à la main (identique à ce que fait jaPBe) :
> PBCompiler PB_EditorOutput.pb
******************************************
PureBasic v4.00 (Windows - x86)
******************************************

Compiling pb_editoroutput.pb
Loading external libraries...
Starting compilation...
Including source: C:\Purebasic400\Compilers\PB_EditorOutput2.pb
59 lines processed.
Creating executable.
Error: Linker
POLINK: error: Unresolved external symbol '_PB_Object_GetOrAllocateID'.
POLINK: error: Unresolved external symbol '_PB_Object_GetObject'.
POLINK: error: Unresolved external symbol '_PB_Object_IsObject'.
POLINK: error: Unresolved external symbol '_PB_Object_EnumerateAll'.
POLINK: error: Unresolved external symbol '_PB_Object_EnumerateStart'.
POLINK: error: Unresolved external symbol '_PB_Object_EnumerateNext'.
POLINK: error: Unresolved external symbol '_PB_Object_EnumerateAbort'.
POLINK: error: Unresolved external symbol '_PB_Object_FreeID'.
POLINK: error: Unresolved external symbol '_PB_Object_Init'.
POLINK: error: Unresolved external symbol '_PB_Object_GetThreadMemory'.
POLINK: error: Unresolved external symbol '_PB_Object_InitThreadMemory'.
POLINK: fatal error: 11 unresolved external(s).

C:\PureBasic400\Compilers>
Avec PB_EditorOutput.pb

Code : Tout sélectionner

#jaPBe_CompilerVersion="4.00"
#jaPBe_IsDebuggerRunning=0
#jaPBe_IsExecute=0
#jaPBe_ExecuteBuild=1
#jaPBe_ExecuteType=0
#jaPBe_OnError=0
#jaPBe_SourcePath=""
#jaPBe_SourceFile=""
IncludePath "C:\PUREBASIC400\JAPBE\Include"
IncludePath ""
IncludeFile "C:\Purebasic400\Compilers\PB_EditorOutput2.pb"
Et PB_EditorOutput2.pb

Code : Tout sélectionner

Prototype   PB_Object_GetOrAllocate   (Objects, Object.l) 
Prototype   PB_Object_GetObject       (Objects, Object.l) 
Prototype   PB_Object_IsObject        (Objects, Object.l) 
Prototype   PB_Object_EnumerateAll    (Objects, ObjectEnumerateAllCallback, *VoidData) 
Prototype   PB_Object_EnumerateStart  (Objects) 
Prototype   PB_Object_EnumerateNext   (Objects, *Object.Long) 
Prototype   PB_Object_EnumerateAbort  (Objects) 
Prototype   PB_Object_Free            (Objects, Object.l) 
Prototype.l PB_Object_Init            (StructureSize.l, IncrementStep.l, ObjectFreeFunction) 
Prototype   PB_Object_GetThreadMemory (MemoryID.l) 
Prototype.l PB_Object_InitThreadMemory(Size.l, InitFunction, EndFunction) 

Global Object_GetOrAllocate   .PB_Object_GetOrAllocate 
Global Object_GetObject       .PB_Object_GetObject 
Global Object_IsObject        .PB_Object_IsObject 
Global Object_EnumerateAll    .PB_Object_EnumerateAll 
Global Object_EnumerateStart  .PB_Object_EnumerateStart 
Global Object_EnumerateNext   .PB_Object_EnumerateNext 
Global Object_EnumerateAbort  .PB_Object_EnumerateAbort 
Global Object_Free            .PB_Object_Free 
Global Object_Init            .PB_Object_Init 
Global Object_GetThreadMemory .PB_Object_GetThreadMemory 
Global Object_InitThreadMemory.PB_Object_InitThreadMemory 

!EXTRN _PB_Object_GetOrAllocateID@8 
!EXTRN _PB_Object_GetObject@8 
!EXTRN _PB_Object_IsObject@8 
!EXTRN _PB_Object_EnumerateAll@12 
!EXTRN _PB_Object_EnumerateStart@4 
!EXTRN _PB_Object_EnumerateNext@8 
!EXTRN _PB_Object_EnumerateAbort@4 
!EXTRN _PB_Object_FreeID@8 
!EXTRN _PB_Object_Init@12 
!EXTRN _PB_Object_GetThreadMemory@4 
!EXTRN _PB_Object_InitThreadMemory@12 

!MOV [v_Object_GetOrAllocate]   , _PB_Object_GetOrAllocateID@8 
!MOV [v_Object_GetObject]       , _PB_Object_GetObject@8 
!MOV [v_Object_IsObject]        , _PB_Object_IsObject@8 
!MOV [v_Object_EnumerateAll]    , _PB_Object_EnumerateAll@12 
!MOV [v_Object_EnumerateStart]  , _PB_Object_EnumerateStart@4 
!MOV [v_Object_EnumerateNext]   , _PB_Object_EnumerateNext@8 
!MOV [v_Object_EnumerateAbort]  , _PB_Object_EnumerateAbort@4 
!MOV [v_Object_Free]            , _PB_Object_FreeID@8 
!MOV [v_Object_Init]            , _PB_Object_Init@12 
!MOV [v_Object_GetThreadMemory] , _PB_Object_GetThreadMemory@4 
!MOV [v_Object_InitThreadMemory], _PB_Object_InitThreadMemory@12 
Probablement un bug avec INCLUDEFILE ?
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

Message par poshu »

Bon, j'ai grosso modo fini par capter et appliquer le concept.

D'un point de vu threadsafe, tu peux nous en dire plus?
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

Tu as mis le doigt sur les deux fonctions que je ne sais pas utiliser... Pour la simple raison que je n'ai pas trouvé d'exemple dans le SDK, et parce qu'elles ne demandent pas de liste d'objets comme premier argument.

Dri :oops:
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

Message par poshu »

Zut, en tous cas merci d'avoir maché le travail pour nous.

Fred? Help?
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

salut dri,

Bon j'ai réussi à implémenter (en partie) les objets pour le projet #1.

Par contre, j'aurai quand même qq questions...

Quand j'écris çà, pour initialiser l'objet database :

DatabaseObjects.l = Object_Init(SizeOf(THIS), 1, @_CloseDatabase())

pourquoi la fonction _CloseDatabase() est-elle réellement appelée dès le début du source ?

et à l'inverse, à la fin du programme, alors que je m'attendais à ce que la fonction soit appelée automatiquement si l'utilisateur n'a lui-même fait CloseDatabase(), elle n'est pas appelée du tout...


[EDIT]
bon j'ai compris pourquoi la fonction _CloseDatabase() est appelée au début du source, puisque c'est Object_GetOrAllocate() qui l'appelle pour réinitialiser/réallouer l'objet/identifiant.

par contre, pour la libération automatique des objets en fin de source, j'ai dû louper un étage...
Image
Dr. Dri
Messages : 2527
Inscription : ven. 23/janv./2004 18:10

Message par Dr. Dri »

je viens de tester et effectivement PB ne semble pas appeller la fonction à la fermeture du programme.

dans ce cas est-ce que dans une lib on peut définir une fonction automatiquement appellée au début et une autre a la fin ?

Dri
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

that is the question !

par contre de toutes facons avec tailbite, c'est possible (voir dans le chm) :

Code : Tout sélectionner

   ProcedureDLL MyLib_Init()
     ; Do some initializing stuff, allocate memory, etc.
   EndProcedure

   ProcedureDLL MyLib_End()
     ; Do some cleaning, free memory, unload third party DLLs, etc.
   EndProcedure
donc en principe grace à Object_EnumerateAll() on devrait pouvoir s'en sortir. mais comment Fred ferait en C/C++
Image
Avatar de l’utilisateur
Flype
Messages : 2431
Inscription : jeu. 29/janv./2004 0:26
Localisation : Nantes

Message par Flype »

çà remarche dans jaPBe si la constante #jaPBe_SourcePath est défini sur le bon dossier.
Image
poshu
Messages : 1138
Inscription : sam. 31/juil./2004 22:32

Message par poshu »

Euh... Ca plante chez moi, meme avec l'IDE de pure, si je coupe le debugger et donc si je crée un executable :/
Répondre