Announcement

Collapse
No announcement yet.

TYPE vs Global (attn Mike/John)

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • TYPE vs Global (attn Mike/John)

    OK Michael, John -
    Removed my 28 globals- inserted a TYPE structure..

    Works well save for 2 that I wanted as Dynamic strings because the size could vary so much (Html page and graphic) -

    Now I have this as a TYPE, but do I need it as a Global or can I try that pointer method?

    And, you mentioned 32 bit pointer vs having all the globals.

    Just looking for more clarification on how much better/more optimized this is/ will be...

    Everything in the structure was a global.

    Code:
    '--------------------------------------
    Type CCSParams
        szMine          As Asciiz * 9
        szVer           As Asciiz * 5
        szCCS           As Asciiz * 28
        szCopyrite      As Asciiz * 22
        IniFile         As Asciiz * %MAX_PATH
        sTunnelLoc      As Asciiz * %MAX_PATH
        hInst           As Long
        hDlg            As Long
        hIcon           As Long
        hMenu           As Long
        pMenu           As Long
        hPop1           As Long
        hPop2           As Long
        hPop3           As Long
        lblHandle       As Long
        txtHandle       As Long
        hStatus         As Long
        IsEvalCopy      As Long
        'Options
        wPort           As Long
        StayOnTop       As Long
        RuninSysTray    As Long
        SysStartup      As Long
        ShowSplash      As Long
        Finished        As Long 'For threads to end
        UseSSL          As Long
        SSLKey          As Asciiz * %MAX_PATH
        SSLCert         As Asciiz * %MAX_PATH
        SSLPort         As Asciiz * 5
        wTimeOut        As Long
        SSLTimeOut      As Long
        ServerIP        As Asciiz * 16
        LogFile         As Asciiz * %MAX_PATH
        BBSDownFile     As Asciiz  * %MAX_PATH'Actual html file
        BBSDownImageFile  As Asciiz * %MAX_PATH  'Actual file to read into memory
        BBSDownString   As Asciiz  * 256    'String to insert into built in html file
    End Type
    
    Global BBSDown          As CCSParams
    Global hCurHand         As Long
    Global g_BBSDownImage   As String
    Global g_BBSDown        As String 'Variable len strings
    '------------------------------------------------------------------------------
    ' Declares
    Scott Turchin
    MCSE, MCP+I
    http://www.tngbbs.com
    ----------------------
    True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

  • #2
    Local BBSDown As CCSParams Pointer

    BBSDown=GlobalAlloc(%GPTR (?), sizeof(CCSParams))
    @BBSDown.szMine="What's Mine Is Mine!!!"
    etc
    SetWindowLong(hWnd,0,BBSDown)

    The idea is to allocate memory for a CCSParams type from global memory and store your data there using pointer notation. Then store the pointer at some offset or other in the window's .cbWndExtra bytes. That's SDK. However, I believe DDT has an analogous setup. I didn't test the above, but that's the general idea.
    Fred
    "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

    Comment


    • #3
      So is my GLOBAL BBSDown as CCSParams incorrect then?

      If I set these using a pointer like this then I can assumeI make a local copy in the next function (ie callback) and can access that data?


      It's confusing, that's why I just used globals but I'd like to use structures and try to do it right

      For a laugh, @BBSDown.szMine="What's Mine Is Mine!!!"

      Actually could never think of a name for APPNAME so just called it "Mine"...

      @BBSDown.szMine="BBSDown!"

      Dunno why but it stuck back in 1995 and been doing it that way since...
      Scott Turchin
      MCSE, MCP+I
      http://www.tngbbs.com
      ----------------------
      True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

      Comment


      • #4
        A global variable can be assigned as a UDT.

        It's really an ideological choice. (1) If you avoid using Globals because you feel you might later duplicate it, i.e. you did not use a distinct naming scheme in the first place such as g_UsersOptions; then (2) you have to store and retrieve the address of your variable, which must remain available at any time you need to access it, in a USER memory or the window's memory (see SetWindowLong/GeWindowLong API)

        You could set your Type to have pointers to the 2 items you mentioned, and retrieve appropriately.

        In the end, it is just how you want to do it. Method 2 it will take a bit more coding, but in the end you are simply avoiding the rare, remote possibility of duplicating the variable name. IMO, that is the real bottom line. Why, because you sill have to fill the typed variable with the values, you still have to access them. In method 2 looks like you would have to do his twice, per your thread previous where you indicate you need to access in 2 different windows in your program. These presumably have their own callbacks as well. When they are closed, what are you going to do to keep the values persistent or saved or is this even germane?
        Rick Angell

        Comment


        • #5
          Now I"m really cornfused.

          I have a function that reads the INI file - so they are set there.
          That is called by WInmain.

          They are used in DialogProc, the callback.

          From there an OPTIONS screen also accesses them, and then the callback function uses them as well -

          And then from THAT callback I write them to an INI file.

          THere area few functions that access them as well, such as a function to load the HTML page into memory every 60 seconds (Caching in case it's changed by user etc).....

          So I went with globals because my naming convention is such that I won't duplicate them, but is the program more bloaty because I'm using the globals or is it better off this way?

          I don't quite understand the USER thing either but I'd be curious if this method with a TYPE is more efficient/faster/less memory etc....
          Scott Turchin
          MCSE, MCP+I
          http://www.tngbbs.com
          ----------------------
          True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

          Comment


          • #6
            SetWindowLongPTR superseds SetWindow Long for compatability with both 32 bit and 64 bit.

            http://msdn.microsoft.com/en-us/libr...98(VS.85).aspx
            Scott Turchin
            MCSE, MCP+I
            http://www.tngbbs.com
            ----------------------
            True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

            Comment


            • #7
              I think the best way to get a conceptual handle on the issues is through the concept of 'data persistence.' If some item of data must persist through function calls, such as, perhaps, the path to a file a user may be editing with a text editor, then globals can be avoided by storing the path (in a type perhaps) in a user defined memory slot (DDT) or cbWndExtra Bytes, or even window properties. Part of the mechanics of the whole thing is passing the pointers to this persistent data about in an application where it is needed. For example, GetWindowLong() will retrieve the pointer from .cbWndExtra bytes for you. At the end of the app dynamically allocated memory must be released. I basically do this in all my apps because I'm in the crowd that doesn't believe in globals in Windows programs.
              Fred
              "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

              Comment


              • #8
                Originally posted by Fred said
                However, I believe DDT has an analogous setup
                A GLOBAL is not just for DDT. It eliminates you taking on the allocation and release responsibilities.

                Code:
                'allocate
                GLOBAL BBSDown          As CCSParams 
                ....
                FUNCTION PBMAIN    '[or WINMAIN
                    BBSDown.szMine="What's Mine Is Mine!!!"
                ...
                CALLBACK FUNCTION MyCallbackProc
                ....
                
                      MSGBOX  BBSDown.szMine
                
                CALLBACK FUNCTION MyOtherCallbackProc
                ....
                
                      MSGBOX  BBSDown.szMine
                BTW a CALLBACK FUNCTION can be used in SDK, many examples in hese forums.
                Rick Angell

                Comment


                • #9
                  OK Lets get to the real reasoning- Globals in a WIndows app, or a PowerBasic app - WHy not???

                  Lets use this member as an example:

                  In Winmain it's loaded:

                  BBSDown.BBSDownImageFile = Load from ini 'But it'd be c:\BBSDown\BBSDown.jpg

                  Now having a global:

                  g_BBDownImageFile - same value, c:\BBSDown\BBSDown.jpg

                  That path may or may not be modified from the Options screen, but it will certainly be used every 60 seconds to reload the image, I think it's faster caching the image that the value points to in memory than reading it in every time someone makes a connection.


                  A) Is the structure saving me memory/performance on 25 of those types of strings - and EVERY one of them can be changed although it would not likely be changed after initial set up. BUt it can....it's an optional thing for the user.

                  B) Globals can be accessed by ANY function I choose - and it's a VERY handy feature....why is it bad?

                  THe entire program is about 110k without the bitmap in it, and even on an old 2 ghz machine it's still lightning fast...

                  I can't associate that data with one specific window though, it's used throughout the application, so is a TYPE really a good thing here?


                  It's a method of coding I guess, I always just assumed if I wanted a variable to be accessed by multiple functions and could not pass it to a callback then it must be global (Hence my question on callbacks.)

                  I can see the point in assigning it to a callback with the SetWindowsLongPTR function and perhaps using a LOCAL copy in there to pass to the functions that require it as most are called from the DialogProc -


                  STill reasoning it out.
                  Last edited by Scott Turchin; 14 Oct 2008, 01:15 PM.
                  Scott Turchin
                  MCSE, MCP+I
                  http://www.tngbbs.com
                  ----------------------
                  True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                  Comment


                  • #10
                    >BBSDown=GlobalAlloc(%GPTR (?), sizeof(CCSParams))

                    CC5+/Win9+ :
                    Code:
                      LOCAL|STATIC|GLOBAL BBSDown AS LONG 
                    
                      GLOBALMEM ALLOC Sizeof(CCSParams) TO  BBSDown
                    MCM
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      OK - I've converted my code, 4 global variables and NO GLOBAL TYPE.

                      So I create a LOCAL "BBSDown as CCSParams".

                      Done.

                      I PASS that to my INI file, Done, it works, loaded - so far so good.

                      Now I"m in my callback, I "should" be able to create a pointer to this or does the TYPE have to be global???


                      Thanks - I think this will actually work quite well to keep variables local...

                      I'm just trying to understand
                      Scott Turchin
                      MCSE, MCP+I
                      http://www.tngbbs.com
                      ----------------------
                      True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                      Comment


                      • #12
                        The definition of a TYPE is used by the compiler to create variables of that type. A PB GLOBAL does not need you to allocate memory for it (GLOBALMEM ALLOC) , doing so is is self-defeating. GLOBAL MEM ALLOC is to create and return a handle to a block of memory you will provide pointer based management of, handle locking and unlocking and movement, etc. of it and take the responsibility of releasing when it is no longer needed.

                        You really need to read the PB manual with regard to DIALOG SET USER, CONTROL SET USER, DIALOG GET USER, CONTROL GET USER to understand how PB provided an easy way for storage and revival of 32bit values, which could be addresses or literal values. Of course using the Set or GetWindowLong approach for storage and retrieval works in a similar manner with you doing the extra coding work for purely SDK do it all with your own all directly API call coded apps.

                        For your program though, the data needs apparently to be persistent for quick access. So you fill it in WinMain and use one of the previously posted methods to store and retrieve. In these situations, IMO, a GLOBAL is a far, cleaner fit and it is unlikely that you will improve performance with the store/pass/retrieve methods of SDK.

                        Changing the value of a structure member is not an issue, the structure is at a fixed place in memory, so the content of the memory at that point is all that changes. So accessing a structure member will get the latest value or if a pointer retrieve the latest value at that address.

                        PB is flexible as you well know, in this case though making everything local is a misnomer because to have useful information you have to have it persistent while the program is running, IOW, you are writing your own "global" variable maintenance routine ... all over the place.
                        Last edited by Richard Angell; 14 Oct 2008, 06:40 PM.
                        Rick Angell

                        Comment


                        • #13
                          Thanks - I'm going to stick to the UDT but it's a global UDT and it's all working, and it is easier to kind of contain all of the data in one place so it does have advantages
                          Scott Turchin
                          MCSE, MCP+I
                          http://www.tngbbs.com
                          ----------------------
                          True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                          Comment


                          • #14
                            DIALOG NEW .... to hDlg

                            "DIALOG SET USER hDLG, n, CSSPARAMS"

                            Value now available in all 'CALLBACK FUNCTIONS' via DIALOG GET USER, and therefore could be passed as a parameter to any support functions called from the CALLBACK FUNCTION.
                            Michael Mattias
                            Tal Systems (retired)
                            Port Washington WI USA
                            [email protected]
                            http://www.talsystems.com

                            Comment


                            • #15
                              Sounds to me like keeping the global variable/variables is a very reasonable thing to do Scott. In any case there isn't any technique you could use in terms of eliminating the globals that would be any faster than having them remain as globals, as alluded to by Richard. With the global it is always one simple memory access to reach the variable - no function calls or anything - just a simple memory lookup. With any technique to eliminate globals there will be one or more function calls between you and the value you need. The function calls add overhead to the program that can't be avoided. So then the question arises, "Why would you want to do this?"

                              The reason I would do it is to force a rather strict regimen on my coding so as to force really looking hard at just what variables are needed in the program and what duration (persistence) each should have. Its terribly easy in the heat of coding to just create a new global every time a variable is needed. I don't like to do that.

                              Also, let me pose this scenerio. Suppose you have a gui application with a hundred procedures. Lets say its sprinkled with several globals that are used in six or eight of those functions. The application works OK. Lets say a year later the user of the application contacts you to make some additions to it. Suppose you add another five or ten functions. Given the GUI model as it is where the order in which procedures are called is totally dependent on the user's actions, can you be absolutely sure that no matter what the user does in the GUI that at all times those globals will contain valid data that when processed in some way won't cause problems? Because its so hard to guarantee this as applications become larger and larger is the reason I tend to avoid globals. In no case is it an issue of making the application smaller or faster because the elimination of globals will in every case I can imagine have the opposite effect.

                              Over in Jose's forum at

                              http://www.jose.it-berater.org/smffo...p?topic=1252.0

                              is an example I made to show how to eliminate globals with the Set/GetWindowLong() technique. Its Sdk though. The issue is this. Suppose you want keypresses/mouse clicks/movements to display immediately on the form that has focus. When the user presses a key or moves the mouse either WM_CHAR or WM_MOUSEMOVE messages will be sent to the Callback. However, displaying something on the screen in response to this must (should) occur in response to a WM_PAINT message. So how does one persist a character keypress across function calls if there are no globals? The above link shows how to do it.
                              Fred
                              "fharris"+Chr$(64)+"evenlink"+Chr$(46)+"com"

                              Comment


                              • #16
                                >Set/GetWindowLong() technique [is] Sdk [style] ...

                                .. to which DIALOG SET/GET USER is the DDT counterpart.

                                My biggest complaint about GLOBALS is it makes code less portable.

                                If a procedure relies only on passed parameters it is easily moved to a DLL ( add a DECLARE) or cut-and-pasted for use in a new application. Can't do that if the procedure uses GLOBALs.

                                ( I also tend to forget the names of those GLOBAL variables, but I think that is more an 'application-specific' limitation...)
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  Originally posted by Michael Mattias View Post
                                  DIALOG NEW .... to hDlg

                                  "DIALOG SET USER hDLG, n, CSSPARAMS"

                                  Value now available in all 'CALLBACK FUNCTIONS' via DIALOG GET USER, and therefore could be passed as a parameter to any support functions called from the CALLBACK FUNCTION.

                                  THat might be very well do-able...
                                  Scott Turchin
                                  MCSE, MCP+I
                                  http://www.tngbbs.com
                                  ----------------------
                                  True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                                  Comment


                                  • #18
                                    Michael - I THINK I finally see what you've been trying to say.

                                    I can pass 8 variables using DIalog SET USER, I had NEVER used that - WAY cool function.

                                    I just eliminated 3 more items out of my global UDT.

                                    Now that said if in WINMAIN I create a LOCAL UDT, and pass the POINTER to that UDT to the callback I could either create a COPY or keep passing that pointer to other functions.


                                    No?
                                    Scott Turchin
                                    MCSE, MCP+I
                                    http://www.tngbbs.com
                                    ----------------------
                                    True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                                    Comment


                                    • #19
                                      No? NO. YES!
                                      Michael Mattias
                                      Tal Systems (retired)
                                      Port Washington WI USA
                                      [email protected]
                                      http://www.talsystems.com

                                      Comment


                                      • #20
                                        Sorry Scott,
                                        I have been watching the post, and just had not time to post.

                                        I think the basics you were looking at were programming styles. Global vs Local and which is better.

                                        I started out with all globals, and working my way back with larger projects because the confusion is start to become real over the years of picking the same global variable (declared the same, but meant for different purposes) and debugging from there.

                                        This may help (took me longer to comment than to code) but maybe its the idea you are after????
                                        Code:
                                        #COMPILE EXE                                                               'Compile as
                                        #DIM ALL                                                                   'Dim EVERYTHING
                                        '------------------------------------------------------------------------------
                                        '   ** Includes **
                                        '------------------------------------------------------------------------------
                                        #IF NOT %DEF(%WINAPI)                                                      'Macro for if not defined, then define it
                                            #INCLUDE "WIN32API.INC"
                                        #ENDIF
                                        '------------------------------------------------------------------------------
                                        
                                        '------------------------------------------------------------------------------
                                        '   ** Constants **                                                        'Constants/Equates
                                        '------------------------------------------------------------------------------
                                        %IDD_DIALOG1 =  101
                                        %IDC_BUTTON1 = 1001
                                        %UNKNOWN = -1                                                              'Bogus value for unknown if value is known
                                        '------------------------------------------------------------------------------
                                        
                                        '------------------------------------------------------------------------------
                                        '   ** Declarations **                                                     'Declare functions, or if not declared then only valid if calling a function that the compiler found before calling the function
                                        '------------------------------------------------------------------------------
                                        DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
                                        DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                                        '*************************************** Replacement for Global ****************************
                                        DECLARE FUNCTION SetGetHwndMain(MainNumber AS DWORD, HwndMain AS DWORD, ResetHwndMain AS DWORD) AS DWORD
                                        '------------------------------------------------------------------------------
                                        
                                        '------------------------------------------------------------------------------
                                        '   ** Main Application Entry Point **
                                        '------------------------------------------------------------------------------
                                        FUNCTION PBMAIN()
                                            ShowDIALOG1 %HWND_DESKTOP                                              'Show the Window/Dialog
                                        END FUNCTION
                                        '------------------------------------------------------------------------------
                                        
                                        '------------------------------------------------------------------------------
                                        '   ** CallBacks **
                                        '------------------------------------------------------------------------------
                                        CALLBACK FUNCTION ShowDIALOG1Proc()
                                            SELECT CASE AS LONG CBMSG
                                                CASE %WM_INITDIALOG
                                                    ' Initialization handler
                                        
                                                CASE %WM_NCACTIVATE
                                                    STATIC hWndSaveFocus AS DWORD
                                                    IF ISFALSE CBWPARAM THEN
                                                        ' Save control focus
                                                        hWndSaveFocus = GetFocus()
                                                    ELSEIF hWndSaveFocus THEN
                                                        ' Restore control focus
                                                        SetFocus(hWndSaveFocus)
                                                        hWndSaveFocus = 0
                                                    END IF
                                        
                                                CASE %WM_COMMAND
                                                    ' Process control notifications
                                                    SELECT CASE AS LONG CBCTL
                                                        CASE %IDC_BUTTON1
                                                            IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                        '                        MSGBOX "%IDC_BUTTON1=" + FORMAT$(%IDC_BUTTON1), %MB_TASKMODAL
                                        '                         MsgBox "HwndDialog = " + str$(hDlg)               'Will not work because hDlg is local to "ShowDialog
                                                                 LOCAL MainNumber AS LONG                          'Bogus unless I am setting the value
                                                                 LOCAL HwndMain AS LONG
                                                                 LOCAL ResetHwndMain AS LONG                       'Am I setting? resetting? or just retrieving the value?
                                                                 SetGetHwndMain(MainNumber, HwndMain, ResetHwndMain)
                                                                 MSGBOX "HwndDialog = " + STR$(HwndMain)            'Will work, because stored in the function, and I retrieved it local to this function
                                                            END IF
                                                    END SELECT
                                            END SELECT
                                        END FUNCTION
                                        '------------------------------------------------------------------------------
                                        
                                        '------------------------------------------------------------------------------
                                        '   ** Dialogs **
                                        '------------------------------------------------------------------------------
                                        FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                                            LOCAL lRslt AS LONG
                                            LOCAL hDlg  AS DWORD                                              '<--- Local to this function only but watch how it becomes global
                                        
                                            DIALOG NEW hParent, "Dialog1", 70, 70, 201, 121, %WS_POPUP OR %WS_BORDER _
                                                OR %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_CAPTION OR %WS_SYSMENU OR _
                                                %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
                                                %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                                                %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
                                                %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
                                                SetGetHwndMain hDlg, hDlg, %TRUE          'Set the value
                                            CONTROL ADD BUTTON, hDlg, %IDC_BUTTON1, "Button1", 10, 10, 65, 15
                                            DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                                            FUNCTION = lRslt
                                        END FUNCTION
                                        '*************************************** Replacement for Global ****************************
                                        FUNCTION SetGetHwndMain(MainNumber AS DWORD, HwndMain AS DWORD, ResetHwndMain AS DWORD) AS DWORD
                                             STATIC hMain AS DWORD
                                             SELECT CASE ResetHwndMain
                                                  CASE %FALSE, %UNKNOWN
                                                       HwndMain = hMain
                                                  CASE = %TRUE
                                                       hMain = MainNumber
                                                       HwndMain = hMain
                                             END SELECT
                                             FUNCTION = %False
                                        END FUNCTION
                                        '------------------------------------------------------------------------------
                                        Engineer's Motto: If it aint broke take it apart and fix it

                                        "If at 1st you don't succeed... call it version 1.0"

                                        "Half of Programming is coding"....."The other 90% is DEBUGGING"

                                        "Document my code????" .... "WHYYY??? do you think they call it CODE? "

                                        Comment

                                        Working...
                                        X