• Welcome to Theos PowerBasic Museum 2017.

News:

Attachments are only available to registered users.
Please register using your full, real name.

Main Menu

PB9 and Objects

Started by Paul Squires, August 22, 2008, 07:58:02 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Paul Squires

None of this post is meant to be negative. I'm just thinking out loud about a few things. I can't wait to get PB9.

I printed off the on-line help information for PB9's objects. I am trying to get a handle on it before my order for PB9 is finally filled.

I seem to understand it all but I did find it a little strange that the terminology for METHODS used "CLASS METHOD" to indicate a private method. I would have thought that "PUBLIC METHOD" or "PRIVATE METHOD" would be more intuitive because it would immediately signal to the reader the scope of the method. I guess that eventually "CLASS METHOD" will be burnt into my head to mean it is private to the Class.  :)

Also, CREATE and DESTROY for Constructors and Destructors. Would have been cool if Constructor and Destructor could have also been accepted as aliases.  :)

Not quite sure I understand the Enumerating Collections example in the Help. Are "InterfaceItem" and "InterfaceItems" already pre-existing interfaces for our use in all Classes or do we somehow need to add them to our Classes first? I still like VB's approach of using "For Each Item In Items" although I'm sure I'll get used to treating the collection like any other For/Next loop counted based on retrieving the number of objects first.

Maybe it's just me but why do new commands seem to take the form of STATEMENT VERB PARAMETER TO RESULT, I guess like the DDT functions do. It seems overly verbose. I mean GLOBALMEM ALLOC count TO vHndl. Okay, it works but vHndl = MEMALLOC(count) seems better at least in my opinionated eyes today.  :)

#INLCUDE ONCE  --  Perfect!

FORWARD REFERENCING  --  Absolutely perfect!!!

I am also a little confused about the BUILD$ fnction. Is it really practical in it's current format? I mean, I see it as the means to overcome the overhead of constantly appending of strings but in practice how would you use it. It seems like all of the strings need to exist prior to calling the function in order to get the real benefits of it, otherwise you simply end up calling the BUILD$ function repeatedly using a small number of strings (still, I can see that being more efficient over simple concatenation). I wonder if it is anymore efficient than the current method I use based on Hutch's appending code. That code essentially leaves the buffer open allowing you to continue appending strings as they become available. Maybe I'm just not visualizing it in practice. I will give it a go once I get the new compiler.  :)



   Local nPos As Long
   Local st     As String
   Local sBuffer As String

   st = "some string containing some example text"
   nPos = AppendStr2( nPos, sBuffer, StrPtr(st), Len(st) )

   st = "another string containing even more text"
   nPos = AppendStr2( nPos, sBuffer, StrPtr(st), Len(st) )

... etc... etc...

   ' Get the result of the appended string
   st = Left$( sBuffer, nPos )


'//
'//  Fast function for concatenating many strings
'//
Function AppendStr2( ByVal stPos   As Long, _
                     ByRef sBuffer As String, _
                     ByVal Addon   As Long, _
                     ByVal lenAdd  As Long _
                     ) Export As Long


    #REGISTER None

    Local pBuffer As Long
   
    ' If the buffer is not large enough to handle the adding
    ' of this string then we need to expand the buffer.
    If stPos + lenAdd + 1 > Len(sBuffer) Then
       sBuffer = sBuffer & String$( Max&(lenAdd, 32 * 1024), 0)   ' increase 32K minimum
    End If

    ' Copy the new string to the end of the buffer
    pBuffer = StrPtr(sBuffer)

    ! cld               ; Read forwards

    ! mov edi, pBuffer  ; Put buffer address In edi
    ! Add edi, stPos    ; Add starting offset To it

    ! mov esi, Addon    ; Put String address In esi
    ! mov ecx, lenAdd   ; length In ecx As counter

    ! rep movsb         ; Copy ecx count Of bytes From esi To edi

    ! mov edx, stPos
    ! Add edx, lenAdd   ; Add stPos And lenAdd For Return value

    ! mov Function, edx

End Function



Paul Squires
FireFly Visual Designer SQLitening Database System JellyFish Pro Editor
http://www.planetsquires.com

José Roca

Quote
Not quite sure I understand the Enumerating Collections example in the Help. Are "InterfaceItem" and "InterfaceItems" already pre-existing interfaces for our use in all Classes or do we somehow need to add them to our Classes first? I still like VB's approach of using "For Each Item In Items" although I'm sure I'll get used to treating the collection like any other For/Next loop counted based on retrieving the number of objects first.

It is no longer in the last version of the help file. It was a leftover of the previous help files, when using the Item property was the only compiler supported way of doing it.

Now you can use the standard IEnumVARIANT enumerator, that is what For... Each uses.


' Retrieve a reference to the collection's enumerator
DIM pEnum AS IEnumVARIANT                 ' // IEnumVARIANT interface
pEnum = pObj.NewEnum   ' All collections have a NewEnum method or property
IF ISNOTHING(pEnum) THEN ... ' Exit

' Iterate through the collection of objects
DIM vItem AS VARIANT
DIM oItem AS DISPATCH <or class name> ' if using Automation
-or-
DIM oItem AS <interface name> ' if using direct calls

DO
   ' Retrieve a reference to the next object in the collection
   ' The first parameter is the number of items to fetch.
   ' The second parameter can be an array of variants.
   ' The third variable can be a long value that will receive the number
   ' of items fetched.
   hr = pEnum.Next(1, vItem, BYVAL %NULL)
   IF hr <> %S_OK THEN EXIT DO
   ' Assign the VT_DISPATCH variant to the object variable
   oItem = vItem : vItem = EMPTY
   IF ISNOTHING(oItem) THEN EXIT DO
   ' Do other calls
   ' ...
   ' ...
   ' ...
   ' Release the object
   oItem = NOTHING
LOOP


Edwin Knoppert

>#INLCUDE ONCE  --  Perfect!
Imo not..
Preventing the reinclusion as done before (#if NOT %DEF( ..) is better then include once.
What if a(n older) module does not have this keyword?

Edwin Knoppert

>InterfaceItems
I don't think PB uses the IEnumerator, the example code looks the ordinary way.
Code as shown above should be the better way (aka foreach)

José Roca

Quote from: Edwin Knoppert on August 22, 2008, 08:46:14 PM
>#INLCUDE ONCE  --  Perfect!
Imo not..
Preventing the reinclusion as done before (#if NOT %DEF( ..) is better then include once.
What if a(n older) module does not have this keyword?


You still can use #IF NOT %DEF( ..), or both at the same time. #INCLUDE ONCE means "include this file if it has not already been included".

Edwin Knoppert


Of course i understand but now it get's discouraged to insert these few lines.

José Roca

#6
 
#INCLUDE ONCE is very useful with big sets of include files like my new winapi files, that also use #IF NOT %DEF. With #IF NOT %DEF, the file has still to be parsed until #ENDIF is found. With #INCLUDE ONCE, the file is not parsed at all if it has already been included. Before it was implemented, I had problems because I was exceeding the limit of nesting levels.

José Roca

 
Quote
Maybe it's just me but why do new commands seem to take the form of STATEMENT VERB PARAMETER TO RESULT, I guess like the DDT functions do. It seems overly verbose. I mean GLOBALMEM ALLOC count TO vHndl. Okay, it works but vHndl = MEMALLOC(count) seems better at least in my opinionated eyes today.

I always have disliked the use of statements instead of functions, mainly because you always have to use a variable for the result, e.g. you can't use IF MemAlloc(count)  = 0 THEN...

Patrice Terrier

#8
QuoteI always have disliked the use of statements instead of functions

All SDK purist will dislike it, it is another form of DDT's propriatary syntax alike style  8)

And for me it envolves extra effort to remember the syntax to use it, i think i will keep using my own API encapsulation ;)

...   
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

James C. Fuller

Quote from: José Roca on August 23, 2008, 06:42:41 AM

Quote
Maybe it's just me but why do new commands seem to take the form of STATEMENT VERB PARAMETER TO RESULT, I guess like the DDT functions do. It seems overly verbose. I mean GLOBALMEM ALLOC count TO vHndl. Okay, it works but vHndl = MEMALLOC(count) seems better at least in my opinionated eyes today.

I always have disliked the use of statements instead of functions, mainly because you always have to use a variable for the result, e.g. you can't use IF MemAlloc(count)  = 0 THEN...


I've decided to use MACROS

James




#COMPILE EXE
#DIM ALL

MACRO FUNCTION ClipGetText()
    MACROTEMP s
    DIM s AS STRING
    CLIPBOARD GET TEXT TO s$
END MACRO = s$
MACRO FUNCTION ClipSetText(Param)
    MACROTEMP i
    DIM i AS LONG
    CLIPBOARD SET TEXT Param TO i
END MACRO = i
FUNCTION PBMAIN () AS LONG

    LOCAL S1,S2 AS STRING
    LOCAL RetVal AS LONG
   
    S1 = "James Fuller"


    IF ClipSetText(S1) THEN
        ?"No ReVal"
    END IF

    S2 = ClipGetText
    ?"S2 = ";S2
   
    WAITKEY$
END FUNCTION

Patrice Terrier

The use of MACRO enlarge the size of the resulting EXE, while a true function won't.


FUNCTION ClipGetText()
    LOCAL s AS STRING
    CLIPBOARD GET TEXT TO s
    FUNCTION = s
END FUNCTION


...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

James C. Fuller

Quote from: Patrice Terrier on August 23, 2008, 02:19:24 PM
The use of MACRO enlarge the size of the resulting EXE, while a true function won't.


FUNCTION ClipGetText()
    LOCAL s AS STRING
    CLIPBOARD GET TEXT TO s
    FUNCTION = s
END FUNCTION


...

????
Macro = No stack frame which is 1 meg and  function call = slower

James

Patrice Terrier

Macro produces largest code when you use it as a replacement for standard subroutines or functions.
Because instead of having the subroutine or function only once in your code, you have it each time the macro code substitution is being done, and if you use this macro say 20 times in your code then you will see the difference in the resulting EXE size.


For example try these two examples based on your code, and tell me which one produces the smallest code size

1 - Using MACRO

MACRO FUNCTION ClipGetText()
    MACROTEMP s
    DIM s AS STRING
    CLIPBOARD GET TEXT TO s$
END MACRO = s$
MACRO FUNCTION ClipSetText(Param)
    MACROTEMP i
    DIM i AS LONG
    CLIPBOARD SET TEXT Param TO i
END MACRO = i
FUNCTION PBMAIN () AS LONG

    LOCAL S1,S2 AS STRING
    LOCAL RetVal AS LONG
   
    S1 = "James Fuller"


    IF ClipSetText(S1) THEN
        ?"No ReVal"
    END IF

    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    ?"S2 = ";S2
   
    WAITKEY$
END FUNCTION


2 - Using standard function

FUNCTION ClipGetText() AS STRING
    LOCAL s AS STRING
    CLIPBOARD GET TEXT TO s
    FUNCTION = s
END FUNCTION
FUNCTION ClipSetText(BYVAL sParam AS STRING) AS LONG
    LOCAL i AS LONG
    CLIPBOARD SET TEXT sParam TO i
    FUNCTION = i
END FUNCTION
FUNCTION PBMAIN () AS LONG

    LOCAL S1,S2 AS STRING
    LOCAL RetVal AS LONG
   
    S1 = "James Fuller"


    IF ClipSetText(S1) THEN
        ?"No ReVal"
    END IF

    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    S2 = ClipGetText
    ?"S2 = ";S2
   
    WAITKEY$
END FUNCTION

Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Edwin Knoppert

#13
They often forget that these calls are also functions.
So reducing one wrapper function isn't gonna help much..

James C. Fuller

You're right of course Patrice!!
My brain was polluted this morning working with Visual Basic 2008 Express Edition trying to get a PB COM server working with it. Duh....

James