Page 1 sur 2

POO et MacOS X

Publié : jeu. 18/avr./2019 10:23
par Philippe_GEORGES
Bonjour à tous,

Juste une remarque : les codes POO posent d'énormes problème de compatibilité avec Mac OS X. C'est dommage, car travaillant avec des bases de données, j'aurais aimé utilisé les exemples de code qui fonctionnent nickel sous windows de MicroDevWeb.....

La question est : vaut il mieux rester en procédural pour avoir vraiment du multiplateforme ?

Ce n'est pas une critique, juste une question.....

Phil

Re: POO et MacOS X

Publié : ven. 19/avr./2019 0:02
par microdevweb
Bonjour,

Je ne possède pas de mac mais ne comprend pas vraiment d'ou pourrait venir le problème. Merci de décrire le problème afin que je comprenne mieux.

Si c'est une dll évidement cela ne peut pas fonctionner, mais je peux te passer le code module

Re: POO et MacOS X

Publié : jeu. 25/avr./2019 15:12
par Philippe_GEORGES
Bonjour

Excuse moi de répondre si tard...

Voilà, si je veux ajouter une localité, liée à un pays, j'ai le message suivant....

[16 :07 :44] [ERREUR] LOCALITE_FIC.pbi (Ligne: 110)
[16 :07 :44] [ERREUR] Invalid parameter not satisfying: index < [_itemArray count]

Maintenant, pour être franc, je n'ai pas encore causé la question.....J'utilise le code final du cours.


Voilà !!! sans doute des précautions à prendre pour l'utilisation sur Cocoa.

Phil

Re: POO et MacOS X

Publié : dim. 28/avr./2019 11:19
par microdevweb
Bonjour Philippe_GEORGES,

Merci de tester ce code sur MacOS et de me dire si cela fonctionne :?

Code : Tout sélectionner

; **************************************************************************************************
; AUTHEUR : BIELEN PIERRE
; PROJECT : 
; MODULE  : SQL.pbi
; **************************************************************************************************
DeclareModule OBJ
  Interface SQL
    query(req.s)
    update(req.s)
    nexRecord()
    firstRecord()
    finishQuery()
    close()
    getString.s(index)
    getLong.l(index)
    getDouble.d(index)
    getFloat.f(index)
    getQuad.q(index)
    getColumnType(column)
    getColumnIndex(columnName.s)
    getDbName.s()
    setString(index,values.s)
    setLong(index,values.l)
    setDouble(index,values.d)
    setFloat(index,values.f)
    setQuad(index,values.q)
  EndInterface
EndDeclareModule
Module OBJ
  
EndModule
DeclareModule SQL
  Global defaultDbName.s 
  Declare new(dbName.s = "")
EndDeclareModule
Module SQL
  EnableExplicit
  UseSQLiteDatabase()
  Structure _struct
    *methods
    id.l
    dbName.s
  EndStructure
  ;-* PRIVATE METHODS
  Procedure createDatabase(*this._struct)
    With *this
      Protected idFile
      If FileSize(\dbName) = -1
        idFile = CreateFile(#PB_Any,\dbName)
        If Not idFile
          MessageRequester("SQL ERROR","Cannot create database",#PB_MessageRequester_Error)
          ProcedureReturn #False
        EndIf
        CloseFile(idFile)
      EndIf
      ProcedureReturn #True
    EndWith
  EndProcedure
  ;}
  
  ;-* PUBLIC METHODS
  Procedure query(*this._struct,req.s)
    With *this
      If Not DatabaseQuery(\id,req)
        MessageRequester("SQL ERROR",req+Chr(10)+DatabaseError())
        ProcedureReturn #False
      EndIf
      ProcedureReturn #True
    EndWith
  EndProcedure
  
  Procedure update(*this._struct,req.s)
    With *this
      If Not DatabaseUpdate(\id,req)
        MessageRequester("SQL ERROR",req+Chr(10)+DatabaseError(),#PB_MessageRequester_Error)
        ProcedureReturn #False
      EndIf
      ProcedureReturn #True
    EndWith
  EndProcedure
  
  Procedure nexRecord(*this._struct)
    With *this
      ProcedureReturn NextDatabaseRow(\id)
    EndWith
  EndProcedure
  
  Procedure finishQuery(*this._struct)
    With *this
      FinishDatabaseQuery(\id)
    EndWith
  EndProcedure
  
  Procedure close(*this._struct)
    With *this
      If IsDatabase(\id)
        If Not CloseDatabase(\id)
          MessageRequester("SQL ERROR","Cannot close database",#PB_MessageRequester_Error)
          ProcedureReturn #False
        EndIf
      EndIf
      FreeStructure(*this)
      ProcedureReturn #True
    EndWith
  EndProcedure
  
  Procedure.s getString(*this._struct,index)
    With *this
      ProcedureReturn GetDatabaseString(\id,index)
    EndWith
  EndProcedure
  
  Procedure.l getLong(*this._struct,index)
    With *this
      ProcedureReturn GetDatabaseLong(\id,index)
    EndWith
  EndProcedure
  
  Procedure.d getDouble(*this._struct,index)
    With *this
      ProcedureReturn GetDatabaseDouble(\id,index)
    EndWith
  EndProcedure
  
  Procedure.f getFloat(*this._struct,index)
    With *this
      ProcedureReturn GetDatabaseFloat(\id,index)
    EndWith
  EndProcedure
  
  Procedure.q getQuad(*this._struct,index)
    With *this
      ProcedureReturn GetDatabaseQuad(\id,index)
    EndWith
  EndProcedure
  
  Procedure setString(*this._struct,index,value.s)
    With *this
      SetDatabaseString(\id,index,value)
    EndWith
  EndProcedure
  
  Procedure setLong(*this._struct,index,value.l)
    With *this
      SetDatabaseLong(\id,index,value)
    EndWith
  EndProcedure
  
  Procedure setDouble(*this._struct,index,value.d)
    With *this
      SetDatabaseDouble(\id,index,value)
    EndWith
  EndProcedure
  
  Procedure setFloat(*this._struct,index,value.f)
    With *this
      SetDatabaseFloat(\id,index,value)
    EndWith
  EndProcedure
  
  Procedure setQuad(*this._struct,index,value.q)
    With *this
      SetDatabaseQuad(\id,index,value)
    EndWith
  EndProcedure
  
  Procedure firstRecord(*this._struct)
    With *this
      ProcedureReturn FirstDatabaseRow(\id)
    EndWith
  EndProcedure
  
  Procedure getColumnType(*this._struct,column)
    With *this
      ProcedureReturn DatabaseColumnType(\id,column)
    EndWith
  EndProcedure
  
  Procedure getColumnIndex(*this._struct,columnName.s)
    With *this
      ProcedureReturn DatabaseColumnIndex(\id,columnName)
    EndWith
  EndProcedure
  
  Procedure.s getDbName(*this._struct)
    With *this
      ProcedureReturn \dbName
    EndWith
  EndProcedure
  ;}
  
  ; CONSTRUCTOR
  Procedure new(dbName.s = "")
    Protected *this._struct = AllocateStructure(_struct)
    With *this
      \methods = ?S_MTH
      If Len(dbName)
        \dbName = dbName
      Else
        \dbName = defaultDbName
      EndIf
      If Not createDatabase(*this)
        ProcedureReturn #False
      EndIf
      \id = OpenDatabase(#PB_Any,\dbName,"","")
      If Not \id
        MessageRequester("SQL ERROR","Cannot open database",#PB_MessageRequester_Error)
        ProcedureReturn #False
      EndIf
      ProcedureReturn *this
    EndWith
  EndProcedure
  
  DataSection
    S_MTH:
    Data.i @query()
    Data.i @update()
    Data.i @nexRecord()
    Data.i @firstRecord()
    Data.i @finishQuery()
    Data.i @close()
    Data.i @getString()
    Data.i @getLong()
    Data.i @getDouble()
    Data.i @getFloat()
    Data.i @getQuad()
    Data.i @getColumnType()
    Data.i @getColumnIndex()
    Data.i @getDbName()
    Data.i @setString()
    Data.i @setLong()
    Data.i @setDouble()
    Data.i @setFloat()
    Data.i @setQuad()
    E_MTH:
  EndDataSection
EndModule

#DB_NAME = "dbTest.db"
; create some records if database file doesn't exist
If FileSize(#DB_NAME) = -1
  db.OBJ::SQL = SQL::new(#DB_NAME)
  ; create countries table
  db\update("CREATE TABLE IF NOT EXISTS countries ("+
            "id INTEGER PRIMARY KEY AUTOINCREMENT,"+
            "name TEXT)")
  ; add some countries
  req.s = "INSERT INTO countries (name) VALUES (?)"
  db\setString(0,"Belgique")
  db\update(req)
  db\setString(0,"France")
  db\update(req)
  db\setString(0,"Espagne")
  db\update(req)
  db\setString(0,"Italie")
  db\update(req)
  ; create cities table
  db\update("CREATE TABLE IF NOT EXISTS cities ("+
            "id INTEGER PRIMARY KEY AUTOINCREMENT,"+
            "name TEXT,"+
            "postalCode TEXT,"+
            "id_country INTEGER"+
            ")")
  ; add some cities
  req.s = "INSERT INTO cities (name,postalCode,id_country) VALUES (?,?,?)"
  db\setString(0,"Trooz")
  db\setString(1,"4870")
  db\setLong(2,1)
  db\update(req)
  db\setString(0,"Liège")
  db\setString(1,"4000")
  db\setLong(2,1)
  db\update(req)
  db\setString(0,"Waremme")
  db\setString(1,"4300")
  db\setLong(2,1)
  db\update(req)
  db\setString(0,"Reims")
  db\setString(1,"69000")
  db\setLong(2,2)
  db\update(req)
  db\setString(0,"Paris")
  db\setString(1,"75000")
  db\setLong(2,2)
  db\update(req)
  ; close database and free object
  db\close()
EndIf
; we read database if its file exists
If FileSize(#DB_NAME)<> -1
  db.OBJ::SQL = SQL::new(#DB_NAME)
  If db\query("SELECT countries.name,cities.name FROM cities,countries WHERE countries.id = cities.id_country")
    While db\nexRecord()
      Debug db\getString(0)+"  "+db\getString(1)
    Wend
    db\close()
  EndIf
EndIf



Re: POO et MacOS X

Publié : dim. 28/avr./2019 11:47
par Mindphazer
Pour ma part, j'ai une erreur à le ligne 64 : le #Database spécifié n'est pas initialisé

(Mac OS X 10.14, PB 5.70 x64)

Re: POO et MacOS X

Publié : lun. 29/avr./2019 11:43
par microdevweb
Merci Mindphazer,

Difficile pour moi de comprendre ce qui ne fonctionne pas car sur win cela fonctionne

Re: POO et MacOS X

Publié : mar. 30/avr./2019 13:22
par Philippe_GEORGES
Hé non, Problème d'initialisation.....et ça marche nickel sous windows.

[14 :18 :35] Attente du démarrage du programme...
[14 :18 :35] Type d'exécutable: MacOSX - x64 (64bit, Unicode)
[14 :18 :35] Exécutable démarré.
[14 :18 :35] [ERREUR] Ligne: 74
[14 :18 :35] [ERREUR] Le #Database spécifié n'est pas initialisé.



Je vais chercher, ça devrait être plus simple à débugger....

Phil

Re: POO et MacOS X

Publié : mar. 30/avr./2019 14:52
par Marc56
C'est bien la POO, mais à force d'ajouter un tas de trucs, on en oublie les bases du codage: la gestion des erreurs.
Parce que là tu as le message du débug, mais une fois compilé, il ne se passerait rien.

:arrow: DatabaseError() après toute commande d'ouverture, fermeture ou requête SQL.

8)

Cela dit, Peut-être que dans l'objet initial, cette gestion y est ?

:wink:

Re: POO et MacOS X

Publié : mar. 30/avr./2019 15:07
par falsam
Marc56 a écrit :C'est bien la POO, mais à force d'ajouter un tas de trucs, on en oublie les bases du codage
Et on s'aperçoit trés vite que POO et PureBasic ne font pas bon ménage.

Purebasic n'est pas un langage adapté pour faire de la poo

Je vous laisse le soin de vérifier la traduction de poo en anglais quand on essaye de le faire fonctionner avec PureBasic

Oui je sais elle était facile ^^

Re: POO et MacOS X

Publié : mer. 01/mai/2019 11:47
par microdevweb
Philippe_GEORGES,

Conseille pour le débogage sous mac. Au niveau de la méthode update,

avant la ligne 74 placer un debug de \id

si la valeur la valeur n'est pas null, MacOs fermerait la db, maintenant pourquoi je ne sais pas.

Re: POO et MacOS X

Publié : mer. 01/mai/2019 14:03
par Philippe_GEORGES
La valeur de \id n'est pas nulle...

Impossible de localiser l'erreur.

Phil

Re: POO et MacOS X

Publié : dim. 26/mai/2019 12:38
par G-Rom
@microdevweb

la poo pb est, disons le franchement imbuvable et n'apporte absolument rien , si ton délire et d'avoir des fonctions dans des structures , utilises des prototypes, ils sont fait pour cela :

Code : Tout sélectionner

Prototype.d MonPseudoObjet_add(a.d,b.d)

Structure MonPseudoObjet
  add.MonPseudoObjet_add
EndStructure

Procedure.d MonPseudoObjet_add(a.d,b.d)
  ProcedureReturn a + b
EndProcedure

Procedure.i new()
  *o.MonPseudoObjet = AllocateStructure(MonPseudoObjet)
  *o\add = @MonPseudoObjet_add()
  ProcedureReturn *o
EndProcedure



*test.MonPseudoObjet = new()

Debug *test\add(53,47) 

Re: POO et MacOS X

Publié : dim. 26/mai/2019 13:59
par Micoute
C'est que la POO vue sous cet angle, est bien plus simple à mettre en œuvre. Merci pour le partage.

Re: POO et MacOS X

Publié : lun. 27/mai/2019 8:21
par microdevweb
@G-Rom

Je sais bien que Pb n'est pas fait pour la oop et que cela demande plus de code (pas bcp plus de temps avec le model de code que je me suis fait), raison pour la-quel j'utilise plus java maintenant. Cependant pour certains projets j'utilise la pseudo oop de pb et également les prototypes pour mes méthodes abstraites.

Code : Tout sélectionner

DeclareModule Person
  
  Prototype.s _attack(*this)
  Structure _struct
    *methods
    name.s
    _attack._attack
  EndStructure
  Declare super(*this._struct,*s_daughter,*E_daughter,name.s)
EndDeclareModule
Module Person
  EnableExplicit
  ;-* PRIVATE METHODS
  
  ;}
  ;-* PUBLIC METHODS
  Procedure.s getName(*this._struct)
   With *this
     ProcedureReturn \name
   EndWith
  EndProcedure
  
  ;}
  ;-* ABSTRACT METHODS
  Procedure.s _attack(*this._struct)
    With *this
      If \_attack
        ProcedureReturn \_attack(*this)
      EndIf
    EndWith
  EndProcedure
  ; CONSTRUCTOR
  Procedure super(*this._struct,*s_daughter,*E_daughter,name.s)
    With *this
      ; allouer la mémoire
      Protected motherLen = ?E_MTH - ?S_MTH,daughterLen = *E_daughter - *s_daughter
      \methods = AllocateMemory(motherLen + daughterLen)
      ; empiler les adresses des méthodes
      MoveMemory(?S_MTH,\methods,motherLen)
      MoveMemory(*s_daughter,\methods + motherLen,daughterLen)
      ; set values
      \name = name
    EndWith
  EndProcedure
  
  DataSection
    S_MTH:
    Data.i @getName()
    Data.i @_attack()
    E_MTH:
  EndDataSection
EndModule

DeclareModule Warrior
  Declare new(name.s)
EndDeclareModule
Module Warrior
  EnableExplicit
  Structure _struct Extends Person::_struct
   
  EndStructure
  ;-* PRIVATE METHODS
  
  ;}
  ;-* PUBLIC METHODS
 
  ;}
  ;-* ABSTRACT METHODS
  Procedure.s _attach(*this._struct)
    With *this
      ProcedureReturn "Warrior "+\name+" attack"
    EndWith
  EndProcedure
  ;}
  ; CONSTRUCTOR
  Procedure new(name.s)
    Protected *this._struct = AllocateStructure(_struct)
    With *this
      Person::super(*this,?S_MTH,?E_MTH,name)
      \_attack = @_attach() ; abstract method address
      ProcedureReturn *this
    EndWith
  EndProcedure
  
  DataSection
    S_MTH:

    E_MTH:
  EndDataSection
EndModule

DeclareModule Magician
  Declare new(name.s)
EndDeclareModule
Module Magician
  EnableExplicit
  Structure _struct Extends Person::_struct
   
  EndStructure
  ;-* PRIVATE METHODS
  
  ;}
  ;-* PUBLIC METHODS
 
  ;}
  ;-* ABSTRACT METHODS
  Procedure.s _attach(*this._struct)
    With *this
      ProcedureReturn "magician "+\name+" attack"
    EndWith
  EndProcedure
  ;}
  ; CONSTRUCTOR
  Procedure new(name.s)
    Protected *this._struct = AllocateStructure(_struct)
    With *this
      Person::super(*this,?S_MTH,?E_MTH,name)
      \_attack = @_attach() ; abstract method address
      ProcedureReturn *this
    EndWith
  EndProcedure
  
  DataSection
    S_MTH:

    E_MTH:
  EndDataSection
EndModule

Interface person
  getName.s()
  attack.s()
EndInterface
Interface warrior Extends person
  
EndInterface
Interface magician Extends person
  
EndInterface

war1.warrior = Warrior::new("warrior 1")
war2.warrior = Warrior::new("warrior 2")
mag1.magician = Magician::new("magician 1")
mag2.magician = Magician::new("magician 2")
Debug war1\attack()
Debug war2\attack()
Debug mag1\attack()
Debug mag2\attack()



Re: POO et MacOS X

Publié : lun. 27/mai/2019 18:29
par G-Rom
Ca reste indigeste quand même , met toi à la place du gars qui va lire ton code, là je vois des copie de mémoires :

Code : Tout sélectionner

Protected motherLen = ?E_MTH - ?S_MTH,daughterLen = *E_daughter - *s_daughter
      \methods = AllocateMemory(motherLen + daughterLen)
On ne comprends rien, enfin, moi si , mais le 1er lambda qui lit la source ne comprend pas pourquoi tu dois faire cela.
utilise des macros pour rendre l'opération d'écriture moins lourde :

Code : Tout sélectionner

; MACRO POUR "SIMPLIFIER" TON CODE INBUVABLE
;
;
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
  Macro PROC_SIZE:4:EndMacro
CompilerElse
  Macro PROC_SIZE:8:EndMacro
CompilerEndIf


Macro USE_AS_CLASS
*method  
EndMacro

Macro CLASS_METHOD(_OBJECT_, _CLASS_ , _NUMBER_)
  _OBJECT_#._CLASS_ = AllocateStructure( _CLASS_ )
  _OBJECT_\method = AllocateMemory( _NUMBER_ * PROC_SIZE )
  _OBJECT_#METHOD_OFFSET = 0
EndMacro

Macro REGISTER_METHOD(_OBJECT_ , _METHOD_)
  PokeI(_OBJECT_#\method + _OBJECT_#METHOD_OFFSET,   @_METHOD_) : _OBJECT_#METHOD_OFFSET + PROC_SIZE
EndMacro

; DECLARATION D'UNE CLASSE AVEC MEMBRE PRIVÉ... 
;
;
Structure Private_Class : USE_AS_CLASS  
  result.f
EndStructure

; Son interface publique
;
;
Interface Class
  add.f(x.f,y.f)
  result.f()
EndInterface

; Declaration des procédures avec TOUJOURS, le premier paramètre qui représente l'objet
;
;
Declare.f Class_add(*self.Private_Class, x.f, y.f)
Declare.f Class_result(*self.Private_Class)

; Le constructeur
;
;
Procedure.i Class_New()
  CLASS_METHOD(*c,Private_Class,2)        ; Notre objet *c de classe "Private_Class" à 2 méthodes
  REGISTER_METHOD(*c ,Class_add())        ; on lui donne les méthodes avec des macros qui rend le code plus clean
  REGISTER_METHOD(*c ,Class_result())     ; ca évite ton code inbuvable.
  ProcedureReturn *c
EndProcedure

; Les méthodes
;
;
Procedure.f Class_add(*self.Private_Class, x.f, y.f)
  *self\result = x+y
  ProcedureReturn *self\result
EndProcedure

Procedure.f Class_result(*self.Private_Class)
  ProcedureReturn *self\result
EndProcedure


; Le test
;
;
Test.Class = Class_New()
Test\add(55,55)
Debug Test\result()
du coup, avec les macros, le constructeur est réduit à cela :

Code : Tout sélectionner

Procedure.i Class_New()
  CLASS_METHOD(*c,Private_Class,2)        ; Notre objet *c de classe "Private_Class" à 2 méthodes
  REGISTER_METHOD(*c ,Class_add())        ; on lui donne les méthodes avec des macros qui rend le code plus clean
  REGISTER_METHOD(*c ,Class_result())     ; ca évite ton code inbuvable.
  ProcedureReturn *c
EndProcedure
en 3 lignes, tu as l'objet créer et les méthodes déclarée copié dans l'objet.

versus :

Code : Tout sélectionner

 Procedure super(*this._struct,*s_daughter,*E_daughter,name.s)
    With *this
      ; allouer la mémoire
      Protected motherLen = ?E_MTH - ?S_MTH,daughterLen = *E_daughter - *s_daughter
      \methods = AllocateMemory(motherLen + daughterLen)
      ; empiler les adresses des méthodes
      MoveMemory(?S_MTH,\methods,motherLen)
      MoveMemory(*s_daughter,\methods + motherLen,daughterLen)
      ; set values
      \name = name
    EndWith
  EndProcedure