Announcement

Collapse
No announcement yet.

What API to use to make PB string compatible dynamic string?

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

  • What API to use to make PB string compatible dynamic string?

    I need to use the API (i think) to create a dynamic string but the address is fixed.

    The memory area is created by a specific api call, an array with String ptrs will be used to access these strings.
    I can not use asciiz.

    Code:
    Global MyArray() As String Ptr
    
    ''''
    
    Redim MyArray( 1 to 1000 )
    Dim pAddr As Dword
    
    pAddr = >> this is the problem, Malloc or sort of, don't know exactly..
    
    MyArray( 1 ) = pAddr
    
    Dim PBString As String At MyArray( 1 )
    (Or string ptr if necessary)
    
    Msgbox PBString

    ------------------
    http://www.hellobasic.com
    hellobasic

  • #2
    Well, if you want dynamic (variable length) strings, you will not be able to specify the address of the string data except by POKEing the data where you want it..

    Your best bet might be what you've started - an array of STRING PTR which you create at a specific memory location with DIM AT.

    What I do not understand is what API call returns an address but does not handle the allocation of the memory?

    Which API call is this?

    MCM

    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      Edwin,

      Look into these API's functions, they were handed to me by Florent Heyworth,
      they are very interesting functions.
      Code:
      SysAllocStringByteLen()
      SysFreeString()
      HTH
      Regards,
      Jules
      Best regards
      Jules
      www.rpmarchildon.com

      Comment


      • #4
        It's not a problem to fool PB, if to use OLE functions (PB does the same).
        Code:
           #Compile Exe
           #Dim All
           #Register  None
           #Include "WIN32API.INC"
        
           Function PbMain
              ' Step 1 - Create Strings
              Dim x(2) As Local Long
              x(0) = SysAllocStringByteLen("Compile", 7)
              x(1) = SysAllocStringByteLen("Compile Exe", 11)
              x(2) = SysAllocStringByteLen("Dim", 3)
              
              ' Let's fool Pb
              ReDim s(2) As String At VarPtr(x(0))
              MsgBox s(0) + $CRLF + s(1) + $CRLF + s(2)
              
        End Function
        But it seems to me that Edwin means that he do not use OLE API to create strings.
        Of course, it's possible to create in memory OLE-similar strings (length of string, string as it is, zero).
        But I am afraid re-allocate statements (a$ = ...)


        ------------------
        E-MAIL: [email protected]

        Comment


        • #5
          i REALLY want the PB strings.
          Wich API/Method is PB using.
          I simply can use my memory using HeapAlloc etc and add 4 bytes (long ) before the string data to simulate the OLE strings.
          This is NOT safe for future windows versions.

          I really need the original PB calls so that String Ptr can be used on them.

          Jules, if i check the PB EXE's, i see the SysAllocStringByteLen() api calls.
          I need confirmation on that.

          In this case i need to create my own memory, for using it i would like to use PB's string pointer.
          Peek$() will be my last resort.


          ------------------
          http://www.hellobasic.com
          hellobasic

          Comment


          • #6
            Semen,

            I have not planned to use any PB code to redim the original contents.
            This will be API/OLE too.

            The memory will be destroyed and rebuild.


            ------------------
            http://www.hellobasic.com
            hellobasic

            Comment


            • #7
              As has been pointed out, PB uses SysAllocStringByteLen in creating strings.
              However, as usual, it's (1) a bad idea to try to fool the compiler, and (2)
              you don't generally gain anything by trying.

              It sounds to me like your best bet here is to PEEK$ and POKE$ the data. If
              you would like to explain what you need to do in more detail, though,
              perhaps a better solution will offer itself.

              ------------------
              Tom Hanlin
              PowerBASIC Staff

              Comment


              • #8
                1) I need a multidimensional array where the second array must be flexible
                2) I need a multidimensional String array where the second array must be flexible

                Let's speak about situation 2 only:

                Global Files() As String

                (f = 1 to nn, depends on opened files)
                x = nn objects for that file
                this can be less or more than in Files( 2...

                ReDim Files( 1 to f, 1 To x )

                Since this is not possible i'm gonna use API's

                A heapalloc to allocate a string ptr array to solve the Files( 1 to f, part
                The address will be stored in a single array.

                The data should be a dynamic string
                It's length is variable per element (1 byte to 200k etc..)
                I wanted to use a string ptr to explore the memory address using instr etc..
                So i would have to copy the data over and over.
                This is a time critical procedure and must be very fast.
                We already have it running where all 'files' are stored in 1 string array.
                After 10000 objects the search is slow.
                10000 objects is fine but not if multiple files are adding another 10000 objects to it.
                We need to break it up.
                (PS, there's no way i rewrite these file systems, it's implemented for 1000's of users already.)

                This is a weird situation because of the dynamic range required for the second entry of the m. array.



                ------------------
                http://www.hellobasic.com
                hellobasic

                Comment


                • #9
                  For situation 1 we have a single array where we use array scan.
                  This array is a simple long containing a crc of another dynamic string array containing the real name of the object.
                  The CRC is found in the 'long' array and it checks the requested objecname.
                  this is because the CRC can be added multiple times plus in this older situation, the file index needs to be check too.

                  The older system handles multiple files in 'one' array (where at the end 4 arrays are used to manage this all)

                  Complex?

                  I can do this with api but then i need peek and poke what i dislike.


                  ------------------
                  http://www.hellobasic.com
                  hellobasic

                  Comment


                  • #10
                    Edwin --
                    What about this organization of multidimensional array (w/o API) ?
                    Code:
                       #Compile Exe
                       #Dim All
                       #Register  None
                       #Include "WIN32API.INC"
                       
                       Function PbMain
                          ' %n - maximum strings in all files
                          %n =   5
                          %nf =  3  ' maximum records in one file
                         
                          Dim s(%n - 1) As String ' Strings
                          Dim r(%n - 1) As Long   ' File id
                          Dim v(%nf - 1) As Long  ' for VarPtr
                         
                          '============== Fill strings =============
                         
                          s(0) = "File 1, Record 1" : r(0) = 1
                          s(1) = "File 2, Record 1" : r(1) = 2
                          s(2) = "File 1, Record 2" : r(2) = 1
                          s(3) = "File 1, Record 3" : r(3) = 1
                          s(4) = "File 2, Record 2" : r(4) = 2
                         
                          '============ Create "array" from single file ====
                          Dim i As Long, k As Long, f As Long
                           
                          For f = 1 To 2
                             k = 0
                             For i = 0 To %n - 1
                                If r(i) = f Then v(k) = StrPtr(s(i)): Incr k
                             Next
                         
                             If k > 0 Then
                                ReDim ss(k - 1) As String At VarPtr(v(0))
                                For i = 0 To k - 1
                                   MsgBox ss(i),, "Array" + Str$(f)
                                Next
                             End If
                          Next
                       End Function
                    ------------------
                    E-MAIL: [email protected]

                    Comment


                    • #11
                      Semen,
                      This is the way we use it.
                      At the end it get's to much items, the search becomes to slow.
                      We use objectnames (e.g. "TEXT1") to find the data.

                      PB:

                      Can i use the code below,
                      It seems the String ptr creates it's own memory address.
                      However, i don't know when or how to destroy the memory.
                      There should be a crash in the following code but does not.

                      Code:
                      #Compile Exe
                      #include "win32api.inc"
                       
                      Function WinMain( ByVal hCurInstance  As Long, _
                                        ByVal hPrevInstance As Long, _
                                        lpszCmdLine         As Asciiz Ptr, _
                                        ByVal nCmdShow      As Long ) As Long
                       
                       
                          Dim L As Long
                          Dim T As String Ptr
                       
                          L = VarPtr( L )
                          T = L
                       
                          @T = "1345sdfyghbfghn"
                       
                      '??????????????????????
                      
                          SysFreeString ByVal L
                          SysFreeString L
                          SysFreeString ByVal T
                          SysFreeString ByVal VarPtr( @T )
                       
                          MsgBox @T
                       
                      End Function
                      ------------------
                      http://www.hellobasic.com
                      hellobasic

                      Comment


                      • #12
                        Already found out that this writes in the wrong mem
                        Don't use it..

                        The SysAlloc.. calls are unicode, PB doen't seem to use it that way.
                        There is a conflict in string length that way.
                        The original API declare will take 2x the size.
                        A string pointer set will show this until you use the string poiter to set new data.
                        Then Len() will work ok.
                        It becomes a bit weird now.

                        It certainly would help me if i get this to work.


                        ------------------
                        http://www.hellobasic.com
                        hellobasic

                        Comment


                        • #13
                          SysAllocStringByteLen is not Unicode...

                          In order to check that a string has been effectively
                          freed you should check GetLastError() after each call
                          to SysFreeString() - a non-zeo return value indicates
                          an error. Use SysStringLen() to find the length of the
                          string.

                          It's my understanding that strings freed are marked for
                          deletion but not immediately freed (they are "lazily" collected).

                          You're asking for trouble when addressing freed strings although
                          the trouble may not be immediately apparent. Set the string
                          pointer to NULL after freeing it - it'll help to avoid
                          errors.

                          Cheers

                          Florent





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

                          Comment


                          • #14
                            Thanks,

                            The freeing was just an example, i declared it wrong anyway.
                            Let's forget that one..

                            The following code becomes importaint to me.
                            See the original length, it's 2x the size.

                            Just don't understand this part.

                            Code:
                            #Compile Exe
                            #include "win32api.inc"
                             
                            Function WinMain( ByVal hCurInstance  As Long, _
                                              ByVal hPrevInstance As Long, _
                                              lpszCmdLine         As Asciiz Ptr, _
                                              ByVal nCmdShow      As Long ) As Long
                             
                             
                                Dim sData   As String
                                Dim pAddr   As Long Ptr
                                Dim Lng     As Long
                                Dim T       As String Ptr
                             
                                sData = Repeat$( 1, "12345678" )
                                pAddr = SysAllocStringLen( ByVal StrPtr( sData ), Len( sData ) )
                             
                                '// Seems to be a must..
                                Lng = pAddr
                                T = VarPtr( Lng )
                             
                             
                                '// Check length of SysAllocStringLen() and original Len of sData..
                             
                                MsgBox Format$( Len( @T ) ) & ", " & Format$( Len( sData ) ) & $CRLF _
                                    & "'" & @T & "'"
                             
                             
                                '// Refill using PB..
                                @T = "1234"
                             
                             
                                '// Check out lengths again..
                                MsgBox Format$( Len( @T ) ) & ", '" & @T & "'"
                             
                             
                             
                             
                             
                                SysFreeString ByVal pAddr
                             
                            End Function
                            ------------------
                            http://www.hellobasic.com
                            hellobasic

                            Comment


                            • #15
                              Hi Edwin

                              you should use SysAllocStringByteLen not SysAllocStringLen
                              which is unicode and use SysStringLen() although you'll
                              probably be okay if you use LEN()

                              Cheers

                              Florent

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

                              Comment


                              • #16
                                Wow!

                                Misread that one completely!!

                                Thanks,



                                ------------------
                                http://www.hellobasic.com
                                hellobasic

                                Comment


                                • #17
                                  Variable-length strings are inherently inefficient in numerous respects, and it's
                                  really not a good plan to try to fool the compiler into thinking your strings are
                                  its strings. This approach does not seem appropriate to the task at hand.

                                  It would almost certainly be safer, faster, and easier if you just did it using
                                  BYTE pointers with HeapAlloc, and wrote your own byte-based search routine to
                                  replace the former use of INSTR.

                                  ------------------
                                  Tom Hanlin
                                  PowerBASIC Staff

                                  Comment


                                  • #18
                                    Tom,

                                    I'll reconsider..

                                    Thanks,


                                    ------------------
                                    http://www.hellobasic.com
                                    hellobasic

                                    Comment


                                    • #19
                                      Btw Tom,

                                      Can you recommend SysAlloc.. above the GetProcessHeap()/HeapAlloc combination?

                                      I expect SysAlloc to be faster.
                                      Then i would prob. use peek$ to access it..

                                      Thanks,


                                      ------------------
                                      http://www.hellobasic.com
                                      hellobasic

                                      Comment


                                      • #20
                                        The SysAlloc APIs are specialized versions of the more generic memory APIs,
                                        so I'd speculate they might be slower. Probably, it doesn't make a great
                                        deal of difference but, when in doubt, try it out.

                                        I don't mean to recommend HeapAlloc in particular. Windows offers a variety
                                        of memory APIs. You might search for some of the previous messages on this
                                        subject.


                                        ------------------
                                        Tom Hanlin
                                        PowerBASIC Staff

                                        Comment

                                        Working...
                                        X