Results 1 to 18 of 18

Thread: [RESOLVED] VB equivalent for C++

  1. #1

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Resolved [RESOLVED] VB equivalent for C++

    Here is a good link to C++ to VB6 code conversion.
    https://www.csun.edu/~lcaretto/me309/cPlusPlus.pdf

    The following posts and excellent answers clarify other issues/solutions for converting from C++ to VB6.


    C++
    Code:
    int    GetCommittedSize() const

    Is this the VB equivalent to the above
    Code:
    Static Function GetCommittedSize() As Long
    Last edited by vb6forever; Oct 21st, 2018 at 09:25 AM.

  2. #2
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: VB equivalent for C++

    There is no const member function equivalent in VB.
    All it's saying is the property is read only / doesn't modify the objects data.

    Code:
    Function GetCommittedSize() As Long

  3. #3

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: VB equivalent for C++

    DEXWERX: Thanks for responding.

    There is no const member function equivalent in VB.
    All it's saying is the property is read only / doesn't modify the objects data.
    Agree, that is why I thought making the VB STATIC would resolve the issue.

    Found this interesting Circular Buffer concept in C++ (CodeProject - see Source link in Class in my zip) and am trying to convert to VB.
    Attached includes original as well as my VB attempt to date.
    Anyone who wants to assist feel free.
    Attached Files Attached Files
    Last edited by vb6forever; Oct 24th, 2018 at 06:05 PM.

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,043

    Re: VB equivalent for C++

    There's no real equivalent of const, nor does there necessarily need to be. Even in C, you could "cast away const", so the word was really just a suggestion to the compiler which it might make use of, or not, to generate improved code. Since you could get rid of it in C, you can get rid of it in VB.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: VB equivalent for C++

    Shaggy Hiker thanks for responding.
    Understand.

    FWIW this is a great discussion on C++ const
    http://duramecho.com/ComputerInforma...wCppConst.html
    Last edited by vb6forever; Oct 19th, 2018 at 09:42 PM.

  6. #6

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: VB equivalent for C++

    Still Not sure how to handle the overloaded operators in DeCommit_Block

    Code:
           TBuffer.sza -= size;      '??? overloaded
           TBuffer.ixa += size;      '??? overloaded
    One thought (??) was:

    Code:
           If TBuffer.sza < 0 then TBuffer.sza = size
           If TBuffer.ixa > 0 then TBUffer.ixa = size

  7. #7
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: VB equivalent for C++

    I'm not sure what you mean by overloaded operators.

    TBuffer.sza -= size;
    TBuffer.ixa += size;

    should translate to

    TBuffer.sza = TBuffer.sza - size
    TBuffer.ixa = TBuffer.ixa + size

    in VB6.

  8. #8

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: VB equivalent for C++

    passel: Thanks for responding and solution.
    My error on "overloaded operator" in this case.
    Can't explain why I marked it such.
    FWIW here is a discussion on overloaded operators.
    https://en.cppreference.com/w/cpp/language/operators

  9. #9
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: VB equivalent for C++

    yeah, I don't see any overloaded operators in that class.
    What I do see is a lot of pointer math.
    You might want to handle the sign bit specifically.

    Code:
    Private Function PtrAdd(ByVal Address As Long, ByVal Offset As Long) As Long
    ' unsigned pointer arithmetic, moves overflow by toggling the sign bit
    ' required when using /LARGEADDRESSAWARE on 64bit windows
        Const SIGN_BIT As Long = &H80000000
        PtrAdd = (Address Xor SIGN_BIT) + Offset Xor SIGN_BIT
    End Function
    Last edited by DEXWERX; Oct 22nd, 2018 at 11:46 AM.

  10. #10

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: VB equivalent for C++

    DEXWERX: Thanks for responding and code.

    Not really sure how to incorporate (where to use) the function with this Class?
    Example please?

  11. #11
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: VB equivalent for C++

    you use it anywhere you're performing math on a pointer.

    Code:
    TBuffer.ixResrv = TBuffer.ixb + TBuffer.szb
    TBuffer.ixResrv = PtrAdd(TBuffer.ixb, TBuffer.szb)
    Also in C/C++ NULL or null is typically a pointer value of zero.
    It's nothing like Null in VB which is more in line with the Database concept of a null value.
    What's worse is that you've used the Constant vbNull which is a Variant Type... used with VarType() or the like.
    It's really just another way of checking if a Variant contains Null, instead of using IsNull etc.

    You could try a variation of this instead.
    Code:
    Private Enum API
        FALSE_ 
        TRUE_ 
        NULL_ = 0&
        [False] = 0
        [True] = 1
        [Null] = 0
    End Enum
    Code:
    ?vbNull
    1
    ?API.Null
    0
    NOTE VB also has Nothing and vbNullString which are both essentially zero pointers.
    Last edited by DEXWERX; Oct 23rd, 2018 at 11:23 AM.

  12. #12

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: VB equivalent for C++

    DEXWERX: Thanks for the response and advice.

    Will reevaluate what I've done and post and update.
    May take a day or two -- hopefully not.

  13. #13

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: VB equivalent for C++

    DEXWERX:

    See Post #3 for new zip #4.
    I believe this is what you had in mind (class for 32 and 64 bit).
    If not please advise.

  14. #14
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: VB equivalent for C++

    So the deal with LARGEADDRESAWARE is that if you enable the flag in your 32bit VB6 exe, and run it on 64bit windows, it will have access to 4GB (minus memory used for shared O/S resources, and process dlls). The only caveat of using this flag, is that any pointer math that doesn't use unsigned integers can overflow when crossing the 2GB boundary. This includes any DLL dependencies that are not written expecting a full 4GB Address space, they may throw a random error.

    you can edit the vbp file and manually add the following to enable it.

    Code:
    [VBCompiler]
    LinkSwitches= /LARGEADDRESSAWARE

    Anyway - back to the original question:
    Code:
     int    GetCommittedSize() const
    really ends up translating to
    Code:
    Public Property Get CommittedSize() As Long
    Using a property is VB's way of hinting that you're not modifying members, where a function hints at side effects.
    Of course it's only a convention and, similar to const, is easily subverted.

    Translation was also simple, because all the math was organized using offsets and sizes - so the only pointer math needed is when returning a final calculated pointer. What you do with those returned pointers in VB is another story. I use an AryMap class to access arbitrary locations as an Array. I'll leave that up the the end users of the class.

    Code:
    'https://www.codeproject.com/Articles/3479/The-Bip-Buffer-The-Circular-Buffer-with-a-Twist
    '/*
    '   Copyright (c) 2003 Simon Cooke, All Rights Reserved
    '
    '   Licensed royalty-free for commercial and non-commercial
    '   use, without warranty or guarantee of suitability for any purpose.
    '   All that I ask is that you send me an email
    '   telling me that you're using my code. It'll make me
    '   feel warm and fuzzy inside. spectecjr@gmail.com
    '
    '*/
    Option Explicit
    
    Private Enum API
        FALSE_
        TRUE_
        NULL_ = 0
    #If False Then
        Dim FALSE_, TRUE_, NULL_
    #End If
    End Enum
    
    Private Declare Function VirtualAlloc Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
    Private Declare Function VirtualFree Lib "kernel32" (ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
    Private Const MEM_COMMIT    As Long = &H1000&
    Private Const MEM_DECOMMIT  As Long = &H4000&
    Private Const PAGE_READWRITE As Long = &H4&
    Private Type SYSTEM_INFO
        dwOemId As Long
        dwPageSize As Long
        lpMinimumApplicationAddress As Long
        lpMaximumApplicationAddress As Long
        dwActiveProcessorMask As Long
        dwNumberOfProcessors As Long
        dwProcessorType As Long
        dwAllocationGranularity As Long
        wProcessorLevel As Integer
        wProcessorRevision As Integer
    End Type
    Private Declare Sub GetSystemInfo Lib "kernel32" (ByRef lpSystemInfo As SYSTEM_INFO)
    
    Private pBuffer As Long
    Private ixa     As Long
    Private sza     As Long
    Private ixb     As Long
    Private szb     As Long
    Private buflen  As Long
    Private ixResrv As Long
    Private szResrv As Long
    
    Private Sub Class_Terminate()
        '// We don't call FreeBuffer, because we don't need to reset our variables - our object is dying
        If pBuffer Then VirtualFree pBuffer, buflen, MEM_DECOMMIT
    End Sub
    
    Public Function AllocateBuffer(Optional ByVal BufferSize As Long = 4096&) As Boolean
        '// Allocate Buffer
        '//
        '// Allocates a buffer in virtual memory, to the nearest page size (rounded up)
        '//
        '// Parameters:
        '//   int buffersize                size of buffer to allocate, in bytes (default: 4096)
        '//
        '// Returns:
        '//   bool                        true if successful, false if buffer cannot be allocated
        If BufferSize <= 0 Then Exit Function
        If pBuffer Then FreeBuffer
        
        Dim si As SYSTEM_INFO
        GetSystemInfo si
        
        ' Calculate nearest page size
        BufferSize = ((BufferSize + si.dwPageSize - 1) \ si.dwPageSize) * si.dwPageSize
        
        pBuffer = VirtualAlloc(NULL_, BufferSize, MEM_COMMIT, PAGE_READWRITE)
        If pBuffer = NULL_ Then Exit Function
        buflen = BufferSize
        AllocateBuffer = True
    End Function
    
    Public Function Clear()
        '///
        '/// \brief Clears the buffer of any allocations.
        '///
        '/// Clears the buffer of any allocations or reservations. Note; it
        '/// does not wipe the buffer memory; it merely resets all pointers,
        '/// returning the buffer to a completely empty state ready for new
        '/// allocations.
        '///
        ixa = 0
        sza = 0
        ixb = 0
        szb = 0
        ixResrv = 0
        szResrv = 0
    End Function
    
    Public Sub FreeBuffer()
        '// Free Buffer
        '//
        '// Frees a previously allocated buffer, resetting all internal pointers to 0.
        '//
        '// Parameters:
        '//   none
        '//
        '// Returns:
        '//   void
        If pBuffer = NULL_ Then Exit Sub
        ixa = 0
        sza = 0
        ixb = 0
        szb = 0
        buflen = 0
        VirtualFree pBuffer, 0&, MEM_DECOMMIT
        pBuffer = NULL_
    End Sub
    
    Public Function Reserve(ByVal Size As Long, ByRef Reserved As Long) As Long
        '// Reserve
        '//
        '// Reserves space in the buffer for a memory write operation
        '//
        '// Parameters:
        '//   int size                amount of space to reserve
        '//   OUT int& reserved        size of space actually reserved
        '//
        '// Returns:
        '//   BYTE*                    pointer to the reserved block
        '//
        '// Notes:
        '//   Will return NULL for the pointer if no space can be allocated.
        '//   Can return any value from 1 to size in reserved.
        '//   Will return NULL if a previous reservation has not been committed.
        Dim FreeSpace As Long
        
        '// We always allocate on B if B exists; this means we have two blocks and our buffer is filling.
        If szb Then
            FreeSpace = BFreeSpace()
            If Size < FreeSpace Then FreeSpace = Size
            If FreeSpace = 0 Then Exit Function
            szResrv = FreeSpace
            Reserved = FreeSpace
            ixResrv = ixb + szb
            Reserve = PtrAdd(pBuffer, ixResrv)
        Else
            '// Block b does not exist, so we can check if the space AFTER a is bigger than the space
            '// before A, and allocate the bigger one.
            FreeSpace = SpaceAfterA()
            If FreeSpace >= ixa Then
                If FreeSpace = 0 Then Exit Function
                If Size < FreeSpace Then FreeSpace = Size
                szResrv = FreeSpace
                Reserved = FreeSpace
                ixResrv = ixa + sza
                Reserve = PtrAdd(pBuffer, ixResrv)
            Else
                If ixa = 0 Then Exit Function
                If ixa < Size Then Size = ixa
                szResrv = Size
                Reserved = Size
                ixResrv = 0
                Reserve = pBuffer
            End If
        End If
    End Function
    
    Sub Commit(ByVal Size As Long)
        '// Commit
        '//
        '// Commits space that has been written to in the buffer
        '//
        '// Parameters:
        '//   int size                number of bytes to commit
        '//
        '// Notes:
        '//   Committing a size > than the reserved size will cause an assert in a debug build;
        '//   in a release build, the actual reserved size will be used.
        '//   Committing a size < than the reserved size will commit that amount of data, and release
        '//   the rest of the space.
        '//   Committing a size of 0 will release the reservation.
        '//
        If Size = 0 Then
            szResrv = 0
            ixResrv = 0
            Exit Sub
        End If
    
        ' // If we try to commit more space than we asked for, clip to the size we asked for.
        If Size > szResrv Then Size = szResrv
    
        ' // If we have no blocks being used currently, we create one in A.
        If sza = 0 And szb = 0 Then
            ixa = ixResrv
            sza = Size
            ixResrv = 0
            szResrv = 0
            Exit Sub
        End If
    
        If ixResrv = sza + ixa Then
            sza = sza + Size
        Else
            szb = szb + Size
        End If
    
        ixResrv = 0
        szResrv = 0
    End Sub
    
    Public Function GetContiguousBlock(ByRef Size As Long) As Long
        '// GetContiguousBlock
        '//
        '// Gets a pointer to the first contiguous block in the buffer, and returns the size of that block.
        '//
        '// Parameters:
        '//   OUT int & size            returns the size of the first contiguous block
        '//
        '// Returns:
        '//   BYTE*                    pointer to the first contiguous block, or NULL if empty.
    
        If sza = 0 Then
            Size = 0
            Exit Function
        End If
    
        Size = sza
        GetContiguousBlock = PtrAdd(pBuffer, ixa)
    End Function
    
    Public Sub DecommitBlock(Size As Long)
        '// DecommitBlock
        '//
        '// Decommits space from the first contiguous block
        '//
        '// Parameters:
        '//   int size                amount of memory to decommit
        '//
        '// Returns:
        '//   nothing
        If Size >= sza Then
            ixa = ixb
            sza = szb
            ixb = 0
            szb = 0
        Else
            sza = sza - Size
            ixa = ixa + Size
        End If
    End Sub
    
    Public Property Get CommittedSize() As Long
        '// GetCommittedSize
        '//
        '// Queries how much data (in total) has been committed in the buffer
        '//
        '// Parameters:
        '//   none
        '//
        '// Returns:
        '//   int                    total amount of committed data in the buffer
        CommittedSize = sza + szb
    End Property
    
    Public Property Get ReservationSize() As Long
        '// GetReservationSize
        '//
        '// Queries how much space has been reserved in the buffer.
        '//
        '// Parameters:
        '//   none
        '//
        '// Returns:
        '//   int                    number of bytes that have been reserved
        '//
        '// Notes:
        '//   A return value of 0 indicates that no space has been reserved
        ReservationSize = szResrv
    End Property
    
    Public Property Get BufferSize() As Long
        '// GetBufferSize
        '//
        '// Queries the maximum total size of the buffer
        '//
        '// Parameters:
        '//   none
        '//
        '// Returns:
        '//   int                    total size of buffer
        BufferSize = buflen
    End Property
    
    Public Property Get IsInitialized() As Boolean
        '// IsInitialized
        '//
        '// Queries whether or not the buffer has been allocated
        '//
        '// Parameters:
        '//   none
        '//
        '// Returns:
        '//   bool                    true if the buffer has been allocated
        IsInitialized = pBuffer <> NULL_
    End Property
    
    Private Property Get SpaceAfterA() As Long
        SpaceAfterA = buflen - ixa - sza
    End Property
    
    Private Property Get BFreeSpace() As Long
        BFreeSpace = ixa - ixb - szb
    End Property
    
    Private Function PtrAdd(ByVal Address As Long, ByVal Offset As Long) As Long
    ' unsigned pointer arithmetic, moves overflow by toggling the sign bit
    ' required when using /LARGEADDRESSAWARE on 64bit windows
        Const SIGN_BIT As Long = &H80000000
        PtrAdd = (Address Xor SIGN_BIT) + Offset Xor SIGN_BIT
    End Function

  15. #15

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: VB equivalent for C++

    DEXWERX:

    Thanks for the info and code changes.
    Will go over them in depth this weekend for my understanding.

    One question though:
    If one is running in 32 bit - and compiled in 32 bit - will Not PtrAdd fail since it
    is using LARGEADDRESAWARE?

    That is the reason I split the pointer addition between 32 and 64 bit.
    I hate to call it pointer addition as really pointer + offset.

    https://stackoverflow.com/questions/...ws-executables
    Last edited by vb6forever; Oct 28th, 2018 at 08:52 PM. Reason: Add Linl

  16. #16
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,224

    Re: VB equivalent for C++

    PtrAdd handles the case when Pointer addition crosses a 31bit boundary. This matters because VB6 doesn't have an unsigned 32bit type. A Long's MSB is a sign bit, which means the max value is 2GB. If you have a pointer to a high address stored in a Long, that would end up >2GB when adding an offset - you will overflow the long type. Unless you have this turned off in the compiler options - you'll throw an overflow exception and most likely crash. This actually doesn't matter for 32bit processes without LAA - because windows will only give it a 2GB address space. Theoretically you'll never have an address >2GB in this case.

    Conversely using PtrAdd in a 32bit process without LAA - doesn't change the final computed pointer. It just gives you more range for the case that does (LAA on a 64bit OS) If you're only dealing with unsigned values <2GB, there is no difference interpreting 32bit pointer values signed or unsigned. You can use PtrAdd in both cases with the only penalty being extra bit toggling (and a function call if you don't inline the operation).


    This whole issue only applies to 32bit processes, it does not address any issues with 64bit. If you want to handle the 64bit VBA case - you actually would use the LongPtr type which should be unsigned. Don't use PtrAdd which assumes bit 32 is a sign bit.

    edit: The .NET analog would be IntPtr.Add()
    Last edited by DEXWERX; Oct 29th, 2018 at 07:18 AM.

  17. #17
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    5,163

    Re: VB equivalent for C++

    @vb6forever: With signed integers you can cross the zero boundary w/o any troubles e.g. ptr = -100, offset = 500 => ptr + offset is 400 (1) and everything is fine around zero boundary. The runtime implements an overflow check around the 2^31 boundary e.g. ptr = &H7FFFFFFF - 100, offset = 500 => pre + offset raises an exception (2).

    The Xor SIGN_BIT trick swaps cases (1) and (2) i.e. PtrAdd(-100, 500) raises overflow error while PtrAdd(&H7FFFFFFF - 100, 500) = &H8000018F is correctly calculated unsigned addition.

    cheers,
    </wqw>

  18. #18

    Thread Starter
    Fanatic Member
    Join Date
    Feb 2017
    Posts
    863

    Re: VB equivalent for C++

    DEXWERX and wqweto:

    Thanks for responding and the excellent explanation.
    I get it.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width