Exemple de compilation dynamique par tube (pipe)

Partagez votre expérience de PureBasic avec les autres utilisateurs.
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Exemple de compilation dynamique par tube (pipe)

Message par Ollivier »

Par manque de temps, je poste juste ce code source de 2010

(explications par djes) Il s'agit d'une calculatrice qui en réalité, fait appel au compilateur PureBasic pour effectuer les calculs.
Ollivier s'est amusé à intégrer quelques autres commandes pour montrer qu'il est en réalité possible d'évaluer autre chose que des opérations mathématiques !

L'exemple est intéressant pour son utilisation des tubes de communication inter-processus (PIPE). Ainsi, le compilateur est lancé une fois au début du programme, et des ordres lui sont donnés par la suite. Une source PB est créée, contenant les opérations tapées par l'utilisateur, et le résultat est récupéré et affiché.

Pas mal de petites choses intéressantes donc !

Note : voir le code actualisé pour PB 5.61 un peu plus bas.

Code : Tout sélectionner

; Actually for Windows only, PB 4.51
; By Ollivier
Global.S Message, Tabulation = "§§", Name = "EquationTest", Expr
Global.S TempDir
TempDir = GetTemporaryDirectory()
Global Cpl, Trust, Margin, MarginWidth = 8, ShutDown
Global NewList MathFunction.S()
Procedure Fatal(Message.S)
            MessageRequester("Erreur fatale", Message + Chr(10) + Chr(10) + "Cliquez sur [Ok] pour quitter...")
            End
EndProcedure
Procedure.S GetMessage(Rank.I, NoUpdate.I = 0)
            If Not NoUpdate
                        Message = ReadProgramString(Cpl)
            EndIf
            ProcedureReturn StringField(Message, Rank, Chr(9) )
EndProcedure
Procedure SetMessage(MyMessage.S)
            Protected Field.S
            Message = ""
            MyMessage = ReplaceString(MyMessage, Tabulation, Chr(9) )
            For I = 0 To CountString(MyMessage, Chr(9) )
                        Field = StringField(MyMessage, I + 1, Chr(9) )   
                        If I = 0
                                    Field = UCase(Field)
                        Else
                                    Message + Chr(9)
                        EndIf
                        Message + Trim(Field)
            Next I
            If ProgramRunning(Cpl)
                        WriteProgramStringN(Cpl, Message)
            EndIf
EndProcedure
Procedure Type(MyLine.S)
            MyLine = ReplaceString(MyLine, "¤", Chr(34) )
            WriteStringN(Trust, Space(MarginWidth * Margin) + MyLine)
EndProcedure
Procedure LogOn()
            Cpl = RunProgram("PBCompiler.EXE", "/STANDBY", #PB_Compiler_Home + "\Compilers", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write | #PB_Program_Hide)
            If Not Cpl
                        Fatal("Compilateur non trouvé !")
            EndIf
            GetMessage(3)
            If GetMessage(1) <> "READY"
                        Fatal("Compilateur non conforme !")
            EndIf
EndProcedure
Procedure LogOff()
            SetMessage("end")
EndProcedure
Global.S Base
Global Margin = 16, ScreenHeight = 48, ButtonWidth = 48, ButtonHeight = 32
Global ButtonQty, ButtonInter = 8, Rank
Procedure.S Beta(Expr.S)
            Protected Result.S
            Trust = CreateFile(#PB_Any, TempDir + Name + ".PB")
            Type("OpenConsole()")
            Type("Global PrivateExpression.S")
            Type("Global PrivateMessage.S")
            Type("PrivateExpression = StrD(" + Expr + ")")
            Type("PrivateMessage = Input()")
            Type("PrintN(PrivateExpression)")
            Type("CloseConsole()")
            CloseFile(Trust)
            SetMessage("source §§ " + TempDir + Name + ".PB")
            SetMessage("target §§ " + TempDir + Name + ".EXE")
            SetMessage("compile")
            If GetMessage(1) = "SUCCESS"
                        Trust = RunProgram(TempDir + Name + ".EXE", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write | #PB_Program_Hide)
                        WriteProgramStringN(Trust, "")
                        Result = ReadProgramString(Trust)
            Else
                        Result = ""
                        While GetMessage(1) <> "OUTPUT"
                                    Result + GetMessage(2, 1) + Chr(10)
                        Wend
            EndIf
            ProcedureReturn Result
EndProcedure
Procedure MainProcess()
            Protected.S Title, MyString, More
            Protected.I ButtonCount, ScreenG, MyVar, Num, SigleOp = 39
            Protected Selec.CHARRANGE
            SetMessage("functionlist")
            GetMessage(1)
            While GetMessage(1) <> "OUTPUT"
                        AddElement(MathFunction() )
                        MathFunction() = Trim(StringField(GetMessage(1, 1), 1, "-") )
            Wend
            ForEach MathFunction()
                        SetMessage("helpdirectory §§ " + StringField(MathFunction(), 1, "(") )
                        If Base = ""
                                    Base = GetMessage(1)
                        Else
                                    If Base <> GetMessage(1)
                                                DeleteElement(MathFunction(), 1)
                                    EndIf
                        EndIf
            Next
            ButtonQty = 19 + ListSize(MathFunction() )
            Rank = ButtonQty / 5 + 1
            InnerWidth = 2 * Margin + Rank * ButtonWidth + (Rank - 1) * ButtonInter
            InnerHeight = 3 * Margin + ScreenHeight + 5 * ButtonHeight + (5 - 1) * ButtonInter
            CalcWin = OpenWindow(#PB_Any, 0, 0, InnerWidth, InnerHeight, "Calculatrice", $CF0001)
            ScreenG = EditorGadget(-1, Margin, Margin, InnerWidth - 2 * Margin, ScreenHeight)
            ResetList(MathFunction() )
            ButtonCount = 0
            MyVar = 7
            For J = 0 To (Rank - 1)
                        For I = 0 To 4
                                    If NextElement(MathFunction() )
                                                Title = StringField(MathFunction(), 1, " ") + "("
                                    Else
                                                If (I > 0) And (I < 4) And (J < (Rank - 1) ) And (J => (Rank - 4) )
                                                            Num = 1
                                                Else
                                                            Num = 0
                                                            If Title = "1"
                                                                        Title = "0"
                                                            Else
                                                                        Title = "X"
                                                            EndIf
                                                EndIf
                                                If Num
                                                            Title = Chr(48 + MyVar)
                                                            MyVar - 3
                                                            If MyVar < 1
                                                                        MyVar + 10
                                                            EndIf
                                                EndIf
                                    EndIf
                                    If ButtonCount => ButtonQty
                                                Y = 2 * Margin + ScreenHeight + (ButtonHeight + ButtonInter) * I
                                                ButtonGadget(-1, Margin + (ButtonWidth + ButtonInter) * J, Y, ButtonWidth, InnerHeight - Margin - Y, "=")
                                                Break 2
                                    EndIf
                                    If Title = "X"
                                                Title = Chr(SigleOp)
                                                If SigleOp = 39
                                                            Title = "C"
                                                EndIf
                                                SigleOp + 1
                                    EndIf
                                    ButtonGadget(Zen, Margin + (ButtonWidth + ButtonInter) * J, 2 * Margin + ScreenHeight + (ButtonHeight + ButtonInter) * I, ButtonWidth, ButtonHeight, Title)
                                    Zen + 1                                    
                                    ButtonCount + 1
                        Next
            Next
            Repeat
                        Evt = WaitWindowEvent()
                        If GetActiveGadget() <> ScreenG
                                    Repeat
                                                Delay(1)
                                                Evt = WindowEvent()
                                    Until Evt = #PB_Event_Gadget
                                    ButtonNo = EventGadget()
                                    More = GetGadgetText(ButtonNo)
                                    If Right(More, 1) = "(" And Len(More) > 1
                                                SelectElement(MathFunction(), ButtonNo)
                                                SetWindowTitle(CalcWin, MathFunction() )
                                    Else
                                                SetWindowTitle(CalcWin, "Calculatrice")
                                    EndIf
                                    If More <> "="
                                                If Ghost
                                                            Ghost = 0
                                                            If ((Asc(More) => 48) And (Asc(More) <= 57) ) Or Right(More, 1) = "("
                                                                        SetGadgetText(ScreenG, "")
                                                            EndIf
                                                EndIf
                                                SendMessage_(GadgetID(ScreenG), #EM_EXGETSEL, #Null, @Selec)
                                                SetGadgetText(ScreenG, GetGadgetText(ScreenG) + More)
                                                Selec\cpMin + Len(More)
                                                Selec\cpMax = Selec\cpMin
                                                SendMessage_(GadgetID(ScreenG), #EM_EXSETSEL, #Null, @Selec)
                                    Else
                                                SetGadgetText(ScreenG, Beta(GetGadgetText(ScreenG) ) )
                                                Ghost | 1
                                    EndIf
                                    If More = "C"
                                                SetGadgetText(ScreenG, "")
                                    EndIf
                                    SetActiveGadget(ScreenG)
                        EndIf
            Until Evt = #PB_Event_CloseWindow
EndProcedure
            LogOn()
                        MainProcess()
            LogOff()
            End
En l'état, il marche uniquement avec le compilateur PureBasic 4.51, de 2010. C'est une calculatrice.

PS: édité par djes
Avatar de l’utilisateur
falsam
Messages : 7244
Inscription : dim. 22/août/2010 15:24
Localisation : IDF (Yvelines)
Contact :

Re: Une calculatrice

Message par falsam »

Présenter un code de calculatrice pas capable de faire 1 + 1 ne présente pas d’intérêt.

PS: édité par djes
Configuration : Windows 11 Famille 64-bit - PB 6.03 x64 - AMD Ryzen 7 - 16 GO RAM
Vidéo NVIDIA GeForce GTX 1650 Ti - Résolution 1920x1080 - Mise à l'échelle 125%
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Une calculatrice

Message par Ollivier »

Merci pour la création de ce sujet.

Il te suffit d'aller dans ton espace personnel, de prendre le compilateur dispo en 2010, et d'exécuter le code source.

C'est une calculatrice. Elle fonctionne.
Et, tant qu'à le dire, meilleurs voeux!
Avatar de l’utilisateur
TazNormand
Messages : 1294
Inscription : ven. 27/oct./2006 12:19
Localisation : Calvados (14)

Re: Une calculatrice

Message par TazNormand »

Salut Ollivier,

j'ai juste envie de dire : pourquoi ce post ???

Alors oui (ou non comme on veut), je ne suis pas allé lire le topic sur le forum anglais, mais c'est quoi l'intérêt de ce post ? Et puis pourquoi ne pas avoir adapté le code à la dernière version de PB ???

N'y voit aucune agression de ma part, juste de la perplexité :oops:
Image
Image
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Une calculatrice

Message par djes »

Il suffit de regarder le code pour voir que c'est un excellent exemple, mais pas vraiment d'une calculatrice ! Et qu'il n'a rien à faire dans la rubrique débutants... Quant à l'utilisation d'une vieille version de PB, c'est parce qu'Ollivier n'a plus rien pour coder maintenant, il ne peut donc montrer que d'anciens trucs... Je vais adapter son code.
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Exemple de compilation dynamique par tube (pipe)

Message par djes »

Voici le code adapté pour PB 5.61. Ca a porté essentiellement sur l'unicode, et a donné lieu au signalement d'un (possible) bug là : http://www.purebasic.fr/english/viewtop ... =4&t=69890

Code : Tout sélectionner

; Actually for Windows only
; By Ollivier
; Adapté par djes pour PB 5.61 (x64)
Global.S Message, Tabulation = "§§", Name = "EquationTest", Expr
Global.S TempDir
TempDir = GetTemporaryDirectory()
Global Cpl, Trust, Margin, MarginWidth = 8, ShutDown
Global NewList MathFunction.S()
Procedure Fatal(Message.S)
  MessageRequester("Erreur fatale", Message + #LF$ + #LF$+ "Cliquez sur [Ok] pour quitter...")
  End
EndProcedure
Procedure.S GetMessage(Rank.I, NoUpdate.I = 0)
  If Not NoUpdate
    Message = ReadProgramString(Cpl)
  EndIf
  ProcedureReturn StringField(Message, Rank, #TAB$ )
EndProcedure
Procedure SetMessage(MyMessage.S)
  Protected Field.S
  Message = ""
  MyMessage = ReplaceString(MyMessage, Tabulation, #TAB$ )
  For I = 0 To CountString(MyMessage, #TAB$ )
    Field = StringField(MyMessage, I + 1, #TAB$ )   
    If I = 0
      Field = UCase(Field)
    Else
      Message + #TAB$
    EndIf
    Message + Trim(Field)
  Next I
  If ProgramRunning(Cpl)
    WriteProgramStringN(Cpl, Message)
  EndIf
EndProcedure
Procedure Type(MyLine.S)
  MyLine = ReplaceString(MyLine, "¤", #DOUBLEQUOTE$ )
  WriteStringN(Trust, MyLine)
EndProcedure
Procedure LogOn()
  Cpl = RunProgram("PBCompiler.EXE", "/STANDBY", #PB_Compiler_Home + "\Compilers", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write | #PB_Program_Hide)
  If Not Cpl
    Fatal("Compilateur non trouvé !")
  EndIf
  GetMessage(3)
  If GetMessage(1) <> "READY"
    Fatal("Compilateur non conforme !")
  EndIf
EndProcedure
Procedure LogOff()
  SetMessage("end")
EndProcedure
Global.S Base
Global Margin = 16, ScreenHeight = 48, ButtonWidth = 48, ButtonHeight = 32
Global ButtonQty, ButtonInter = 8, Rank
Procedure.S Beta(Expr.S)
  Protected Result.S
  Trust = CreateFile(#PB_Any, TempDir + Name + ".PB")
  If Trust    
    Type("OpenConsole()")
    Type("Global PrivateExpression.S")
    Type("Global PrivateMessage.S")
    Type("PrivateExpression = StrD(" + Expr + ")")
    ;Type("PrivateMessage = Input()")
    Type("PrintN(PrivateExpression)")
    Type("CloseConsole()")
    CloseFile(Trust)

    SetMessage("source §§ " + TempDir + Name + ".PB")
    SetMessage("target §§ " + TempDir + Name + ".EXE")
    SetMessage("compile §§ console")

    If GetMessage(1) = "SUCCESS"
      Trust = RunProgram(TempDir + Name + ".EXE", "", "", #PB_Program_Open | #PB_Program_Read | #PB_Program_Write | #PB_Program_Hide | #PB_Program_Error)
      While ProgramRunning(Trust)
        If AvailableProgramOutput(Trust)
          Result.s + ReadProgramString(Trust, #PB_Unicode)
        EndIf
      Wend
      CloseProgram(trust)
    Else
      Result = ""
      While GetMessage(1) <> "OUTPUT"
        Result + GetMessage(2, 1) + #LF$
      Wend
    EndIf
    ProcedureReturn Result
  Else
    Fatal("Impossible de créer le fichier " + TempDir + Name + ".PB")
  EndIf
EndProcedure
Procedure MainProcess()
  Protected.S Title, MyString, More
  Protected.I ButtonCount, ScreenG, MyVar, Num, SigleOp = 39
  Protected Selec.CHARRANGE
  SetMessage("functionlist")
  GetMessage(1)
  While GetMessage(1) <> "OUTPUT"
    AddElement(MathFunction() )
    MathFunction() = Trim(StringField(GetMessage(1, 1), 1, "-") )
  Wend
  ForEach MathFunction()
    SetMessage("helpdirectory §§ " + StringField(MathFunction(), 1, "(") )
    If Base = ""
      Base = GetMessage(1)
    Else
      If Base <> GetMessage(1)
        DeleteElement(MathFunction(), 1)
      EndIf
    EndIf
  Next
  ButtonQty = 19 + ListSize(MathFunction() )
  Rank = ButtonQty / 5 + 1
  InnerWidth = 2 * Margin + Rank * ButtonWidth + (Rank - 1) * ButtonInter
  InnerHeight = 3 * Margin + ScreenHeight + 5 * ButtonHeight + (5 - 1) * ButtonInter
  CalcWin = OpenWindow(#PB_Any, 0, 0, InnerWidth, InnerHeight, "Calculatrice", $CF0001)
  ScreenG = EditorGadget(-1, Margin, Margin, InnerWidth - 2 * Margin, ScreenHeight)
  ResetList(MathFunction() )
  ButtonCount = 0
  MyVar = 7
  For J = 0 To (Rank - 1)
    For I = 0 To 4
      If NextElement(MathFunction() )
        Title = StringField(MathFunction(), 1, " ") + "("
      Else
        If (I > 0) And (I < 4) And (J < (Rank - 1) ) And (J => (Rank - 4) )
          Num = 1
        Else
          Num = 0
          If Title = "1"
            Title = "0"
          Else
            Title = "X"
          EndIf
        EndIf
        If Num
          Title = Chr(48 + MyVar)
          MyVar - 3
          If MyVar < 1
            MyVar + 10
          EndIf
        EndIf
      EndIf
      If ButtonCount => ButtonQty
        Y = 2 * Margin + ScreenHeight + (ButtonHeight + ButtonInter) * I
        ButtonGadget(-1, Margin + (ButtonWidth + ButtonInter) * J, Y, ButtonWidth, InnerHeight - Margin - Y, "=")
        Break 2
      EndIf
      If Title = "X"
        Title = Chr(SigleOp)
        If SigleOp = 39
          Title = "C"
        EndIf
        SigleOp + 1
      EndIf
      ButtonGadget(Zen, Margin + (ButtonWidth + ButtonInter) * J, 2 * Margin + ScreenHeight + (ButtonHeight + ButtonInter) * I, ButtonWidth, ButtonHeight, Title)
      Zen + 1   
      ButtonCount + 1
    Next
  Next
  Repeat
    Evt = WaitWindowEvent()
    If Evt = #PB_Event_Gadget    
      ButtonNo = EventGadget()
      More = GetGadgetText(ButtonNo)        
      ;Debug more
      ;Debug ButtonNo
      If ButtonNo <> ScreenG   
        If Right(More, 1) = "(" And Len(More) > 1
          SelectElement(MathFunction(), ButtonNo)
          SetWindowTitle(CalcWin, MathFunction() )
        Else
          SetWindowTitle(CalcWin, "Calculatrice")
        EndIf
        If More <> "="
          If Ghost
            Ghost = 0
            If ((Asc(More) => 48) And (Asc(More) <= 57) ) Or Right(More, 1) = "("
              SetGadgetText(ScreenG, "")
            EndIf
          EndIf
          SendMessage_(GadgetID(ScreenG), #EM_EXGETSEL, #Null, @Selec)
          SetGadgetText(ScreenG, GetGadgetText(ScreenG) + More)
          Selec\cpMin + Len(More)
          Selec\cpMax = Selec\cpMin
          SendMessage_(GadgetID(ScreenG), #EM_EXSETSEL, #Null, @Selec)
        Else
          SetGadgetText(ScreenG, Beta(GetGadgetText(ScreenG) ) )
          Ghost | 1
        EndIf
        If More = "C"
          SetGadgetText(ScreenG, "")
        EndIf
        SetActiveGadget(ScreenG)
      EndIf
    EndIf
  Until Evt = #PB_Event_CloseWindow
EndProcedure
LogOn()
MainProcess()
LogOff()
End
Avatar de l’utilisateur
djes
Messages : 4252
Inscription : ven. 11/févr./2005 17:34
Localisation : Arras, France

Re: Exemple de compilation dynamique par tube (pipe)

Message par djes »

Un petit post pour dire que j'ai modifié hier le post d'entête, le sujet, et que j'ai rajouté un code fonctionnel en pb 5.61. Ollivier, si ça ne te convient pas, fais signe !
Ollivier
Messages : 4190
Inscription : ven. 29/juin/2007 17:50
Localisation : Encore ?
Contact :

Re: Exemple de compilation dynamique par tube (pipe)

Message par Ollivier »

Merci pour la qualité de ton geste et de ta confiance.
Répondre