Announcement

Collapse

Maintenance

The forum could be offline for 30-60 minutes in the very near future for maintenance (said 3pm Pacific). I was behind on getting this notice. I do apologize.
See more
See less

Dynamic Dynamic strings and the misuse of STRPTR.

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

  • Dynamic Dynamic strings and the misuse of STRPTR.

    Hey Folks,

    The dynamic string allocation question and my own "String Quickie" raise some interesting questions about string pointers. And I think there's a good deal of confusion about them.

    I'm talking about type STRING, PB's dynamic strings (allocated by OLE, stored in ASCII, and managed by an internal handle-based system). I'll call them pbstrings for short.

    The PB manuals tell us, correctly, that if we want a pointer to a pbstring's data, to use STRPTR, not VARPTR. It's exactly what you want when passing a data address to C or whatever.

    But it's exactly what you DON'T want if you're using it for internal dreferencing to pbStrings. I have code to prove this following this message.

    If you want to dereference a string pointer as ASCIIZ data, then you want STRPTR. But if you want to dereference it as the pbstring it is, you want VARPTR.

    The syntax can seem counterintuitive:

    Given:
    local pS as string ptr, pZ as asciiz ptr, S as string

    pS = strptr( S) 'THIS IS WRONG!
    pS = varptr( S) 'THIS IS RIGHT
    pZ = strptr( S) 'THIS IS RIGHT

    You'd think you want to use STRPTR() to assign to a STRING POINTER, but not so. We don't want a pointer to the data, we want the internal handle so PB can handle it correctly.

    Tested code follows in first reply.

    The upshot of all this is that pb has a nice string subsystem. It allocates and disposes of OLE strings for us, but engine isn't exposed. It'd be great, for dynamic allocation needs, if we could tell PB, "I need another pstring. Give me the handle, and YOU remember to destroy it along with the rest when my program finishes."

    Regards,
    Brad


    ------------------


    [This message has been edited by Bradley Olson (edited December 14, 2000).]

  • #2
    'Test of string pointers
    'Brad Olson, Dec 2000

    $COMPILE EXE
    $DIM ALL
    $DEBUG ERROR ON

    %nStrings = 3000
    %SizeStrings = 70
    %printN = 1000 'Print every n strings for progress feedback

    GLOBAL S() AS STRING 'Test source array of strings
    GLOBAL S2() AS STRING 'Test destination array of strings
    GLOBAL pS() AS STRING PTR 'Pointers assigned with STRPTR
    GLOBAL pV() AS STRING PTR 'Pointers assigned with VARPTR
    GLOBAL pA() AS ASCIIZ PTR 'Pointers assigned by STRPTR

    FUNCTION PBMAIN
    LOCAL A$, i&, n&
    DIM S( %nStrings), S2( %nStrings)
    DIM pS( %nStrings), pV( %nStrings), pA( %nStrings)
    PRINT "Beginning test of string pointers."
    PRINT "Fill source array with PB dynamic string's."
    FOR i& = 1 TO %nStrings
    A$ = "This is" + STR$( i&) + ". "
    n& = %sizeStrings \ LEN( A$)
    S( i&) = REPEAT$( n&, a$)
    IF i& MOD %printN = 0 THEN PRINT " "; s(i&)
    NEXT
    PRINT "Assign pointers to pointer arrays."
    FOR i& = 1 TO %nStrings
    pS( i&) = STRPTR( s( i&))
    pA( i&) = STRPTR( s( i&))
    pV( i&) = VARPTR( s( i&))
    NEXT

    $IF 0 'THIS BOMBS, change the zero to 1 to prove it.
    PRINT "String=String assign via STRPTR."
    FOR i& = 1 TO %nStrings
    S2( i&) = @pS( i&)
    IF i& MOD %printN = 0 THEN PRINT s2( i&)
    NEXT
    $ENDIF

    $IF 1
    PRINT "String=String assign via VARPTR."
    FOR i& = 1 TO %nStrings
    S2( i&) = @pV( i&)
    IF i& MOD %printN = 0 THEN PRINT s2( i&)
    NEXT
    $ENDIF

    $IF 1
    PRINT "String=ASCIIZ assign via STRPTR."
    FOR i& = 1 TO %nStrings
    S2( i&) = @pA( i&)
    IF i& MOD %printN = 0 THEN PRINT s2( i&)
    NEXT
    $ENDIF

    END FUNCTION


    ------------------

    Comment


    • #3
      Brad,

      The distinction between StrPtr() and VarPtr() is clear enough, its pretty
      much a case of know what you are getting, StrPtr() returns the ADDRESS
      of the character data in the string, VarPtr() returns the ADDRESS of the
      handle of the string.

      When you use the POINTER operator in PowerBASIC on a dynamic string handle
      you are getting what used to be a C runtime error "Different levels of
      indirection". Basically a pointer to a pointer which is fine if thats what
      you need but a problem if its not.

      ===========================================================================
      The upshot of all this is that pb has a nice string subsystem. It
      allocates and disposes of OLE strings for us, but engine isn't exposed.
      It'd be great, for dynamic allocation needs, if we could tell PB, "I need
      another pstring. Give me the handle, and YOU remember to destroy it along
      with the rest when my program finishes."
      ===========================================================================

      This is in fact easy to do, just use the 2 API calls from oleaut32,
      SysAllocStringByteLen() and SysFreeString() and you can manage your own
      with no problems at all.

      Regards,

      [email protected]

      ------------------
      hutch at movsd dot com
      The MASM Forum

      www.masm32.com

      Comment


      • #4
        I have to agree with Bradley... The following code shows four ways of
        using string pointers. But notice the confusing syntax of the third
        way. Intuition would lead one to want to declare p3 as a STRING PTR,
        since we use p3 = STRPTR(s3), but doing that fails.

        Code:
        #COMPILE EXE
        #DIM ALL
        FUNCTION PBMAIN
           'Four ways to use string pointers
           LOCAL s1 AS STRING, p1 AS STRING PTR
           LOCAL s2 AS STRING, p2 AS STRING PTR
           LOCAL s3 AS STRING, p3 AS ASCIIZ PTR
           LOCAL s4 AS ASCIIZ *40, p4 AS ASCIIZ PTR
           '1st way
              p1 = STRPTR(s1)
              @p1 = "This is the first way"
              MSGBOX @p1
           '2nd way
              s2 = "This is the second way"
              p2 = VARPTR(s2)
              MSGBOX @p2
           '3rd way
              s3 = "This is the third way"
              p3 = STRPTR(s3)
              MSGBOX @p3
           '4th way
              s4 = "This is the fourth way"
              p4 = VARPTR(s4)
              MSGBOX @p4
        END FUNCTION
        ------------------

        Comment

        Working...
        X