Results 1 to 22 of 22

Thread: [VB6] Dereferencing Pointers sans CopyMemory

  1. #1

    Thread Starter
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Arrow [VB6] Dereferencing Pointers sans CopyMemory

    Here are several functions which retrieves the value or data located at the memory address specified by the given pointer. These functions perform the inverse operation of VarPtr, StrPtr and ObjPtr. Rather than using the ubiquitous CopyMemory, alternative APIs are presented instead.


    The API declarations:
    Code:
    Private Declare Function lstrlenA Lib "kernel32.dll" (ByVal lpString As Long) As Long
    
    Private Declare Function CopyBytes Lib "msvbvm60.dll" Alias "__vbaCopyBytes" (ByVal ByteLen As Long, ByVal Destination As Long, ByVal Source As Long) As Long
    Private Declare Function GetMem1 Lib "msvbvm60.dll" (ByVal Addr As Long, ByRef RetVal As Byte) As Long
    Private Declare Function GetMem2 Lib "msvbvm60.dll" (ByVal Addr As Long, ByRef RetVal As Integer) As Long
    Private Declare Function GetMem4 Lib "msvbvm60.dll" (ByVal Addr As Long, ByRef RetVal As Long) As Long
    Private Declare Function GetMem8 Lib "msvbvm60.dll" (ByVal Addr As Long, ByRef RetVal As Currency) As Long
    Private Declare Function ObjSetAddRef Lib "msvbvm60.dll" Alias "__vbaObjSetAddref" (ByRef objDest As Object, ByVal pObject As Long) As Long
    Private Declare Function PutMem4 Lib "msvbvm60.dll" (ByVal Addr As Long, ByVal NewVal As Long) As Long
    
    Private Declare Function SysAllocString Lib "oleaut32.dll" (Optional ByVal pszStrPtr As Long) As Long
    Private Declare Function SysAllocStringByteLen Lib "oleaut32.dll" (Optional ByVal pszStrPtr As Long, Optional ByVal Length As Long) As String
    Private Declare Function SysReAllocString Lib "oleaut32.dll" (ByVal pBSTR As Long, Optional ByVal pszStrPtr As Long) As Long

    The pointer dereferencing functions:
    Code:
    'Retrieves the Byte value from the specified memory address
    Public Function GetBytFromPtr(ByVal Ptr As Long) As Byte
        GetMem1 Ptr, GetBytFromPtr
    End Function
    
    'Retrieves the Integer value from the specified memory address
    Public Function GetIntFromPtr(ByVal Ptr As Long) As Integer
        GetMem2 Ptr, GetIntFromPtr
    End Function
    
    'Retrieves the Long value from the specified memory address
    Public Function GetLngFromPtr(ByVal Ptr As Long) As Long
        GetMem4 Ptr, GetLngFromPtr
    End Function
    
    'Retrieves the Currency value from the specified memory address
    Public Function GetCurFromPtr(ByVal Ptr As Long) As Currency
        GetMem8 Ptr, GetCurFromPtr
    End Function
    
    'Returns a copy of a null-terminated ANSI string (LPSTR/LPCSTR) from the given pointer
    Public Function GetStrFromPtrA(ByVal Ptr As Long) As String
        GetStrFromPtrA = SysAllocStringByteLen(Ptr, lstrlenA(Ptr))
    End Function
    
    'Returns a copy of a null-terminated Unicode string (LPWSTR/LPCWSTR) from the given pointer
    Public Function GetStrFromPtrW(ByVal Ptr As Long) As String
        #If WantFasterWay Then
        PutMem4 VarPtr(GetStrFromPtrW), SysAllocString(Ptr)
        #Else
        SysReAllocString VarPtr(GetStrFromPtrW), Ptr
        #End If
    End Function
    
    'Returns a counted Object reference from the given pointer
    Public Function GetObjFromPtr(ByVal Ptr As Long) As Object
        ObjSetAddRef GetObjFromPtr, Ptr
    End Function
    
    'Returns a shallow copy of a UDT from the given pointer (replace As UDT with the desired type)
    Public Function GetUDTFromPtr(ByVal Ptr As Long) As UDT
        CopyBytes LenB(GetUDTFromPtr), VarPtr(GetUDTFromPtr), Ptr
    End Function

    Sample usage:
    Code:
    'In a standard (.BAS) module
    
    Private Type UDT        'Len  LenB
                            '---------
        Byt As Byte         '  1     4  <-- Padded so that next member is DWORD aligned
        Bln As Boolean      '  2     2
        Int As Integer      '  2     2
        Lng As Long         '  4     4
        Obj As Object       '  4     4
        Sng As Single       '  4     4
        Str As String       '  4     4
        Cur As Currency     '  8     8
        Dtm As Date         '  8     8
        Dbl As Double       '  8     8
        Vnt As Variant      ' 16    16
        FLS As String * 40  ' 40    80  <-- Unicode in memory; ANSI when written to disk
                            '---------
    End Type                '101   144
    Code:
    Public Sub DerefPtrs()    'Call from the Immediate Window
        Dim UDT As UDT
    
        Debug.Print
        Debug.Print "GetBytFromPtr = &H"; Hex$(GetBytFromPtr(VarPtr(CByte(&HAD))))
        Debug.Print "GetIntFromPtr = &H"; Hex$(GetIntFromPtr(VarPtr(&HEAD)))
        Debug.Print "GetLngFromPtr = &H"; Hex$(GetLngFromPtr(VarPtr(&HADC0FFEE)))
        Debug.Print "GetCurFromPtr = "; GetCurFromPtr(VarPtr(1234567890.1234@))
        Debug.Print "GetStrFromPtrW = """; GetStrFromPtrW(StrPtr(App.Title)); """"
        Debug.Print "GetObjFromPtr = """; GetObjFromPtr(ObjPtr(App)).Path; """"
        Debug.Print
    
        With UDT
            .Byt = &HFF
            .Bln = True
            .Int = &H7FFF
            .Lng = &H7FFFFFFF
             Set .Obj = New Collection
            .Sng = 3.402823E+38!
            .Str = "Cwm Fjord Bank Glyphs Vext Quiz"
            .Cur = 922337203685477.5807@
            .Dtm = Now
            .Dbl = 4.94065645841247E-324
            .Vnt = CDec(7.92281625142643E+27)
            .FLS = "Fix Problem Quickly With Galvanized Jets"
        End With
    
        With GetUDTFromPtr(VarPtr(UDT))
            Debug.Print "Byt = &H"; Hex$(.Byt)
            Debug.Print "Bln = "; .Bln
            Debug.Print "Int = &H"; Hex$(.Int)
            Debug.Print "Lng = &H"; Hex$(.Lng)
            Debug.Print "Obj = """; TypeName(.Obj); """"
            Debug.Print "Sng = "; .Sng
            Debug.Print "Str = """; .Str; """"
            Debug.Print "Cur = "; .Cur
            Debug.Print "Dtm = "; .Dtm
            Debug.Print "Dbl = "; .Dbl
            Debug.Print "Vnt = "; .Vnt
            Debug.Print "FLS = """; .FLS; """"
    
           'Cleanup stolen references
            PutMem4 VarPtr(.Obj), 0&
            PutMem4 VarPtr(.Str), 0&
        End With
    End Sub



    References:

    Attached Files Attached Files
    Last edited by Bonnie West; Nov 29th, 2017 at 05:59 AM.
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  2. #2
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    Thanks for sharing this.
    Last edited by Jonney; Jan 30th, 2013 at 01:05 AM.

  3. #3

    Thread Starter
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    Here are the benchmark results (of the attached project below) which compares the performance of the aforementioned APIs against the general-purpose CopyMemory (a.k.a. RtlMoveMemory) API. Function names that ends in 1 uses CopyMemory while those that ends in 2 employs one of the alternative APIs. All times are in seconds.

    Code:
    +-----------------------------------------------------------------------+
    |   10,000,000   |   1st  |   2nd  |   3rd  |   4th  |   5th  ||  Ave.  |
    |----------------+--------+--------+--------+--------+--------++--------|
    | GetBytFromPtr1 | 0.8777 | 0.8587 | 0.9396 | 0.8610 | 0.8776 || 0.8829 |
    | GetBytFromPtr2 | 0.4139 | 0.4138 | 0.3837 | 0.4139 | 0.3970 || 0.4045 |
    |                |        |        |        |        |        ||        |
    | GetIntFromPtr1 | 0.8828 | 0.8707 | 0.8657 | 0.8807 | 1.2831 || 0.9566 |
    | GetIntFromPtr2 | 0.4201 | 0.4193 | 0.4079 | 0.5599 | 0.4082 || 0.4431 |
    |                |        |        |        |        |        ||        |
    | GetLngFromPtr1 | 0.6847 | 0.6707 | 0.6707 | 1.0215 | 0.6709 || 0.7437 |
    | GetLngFromPtr2 | 0.4387 | 0.4387 | 0.3830 | 0.4475 | 0.3631 || 0.4142 |
    |                |        |        |        |        |        ||        |
    | GetCurFromPtr1 | 0.7195 | 1.0443 | 0.7087 | 0.7109 | 0.7088 || 0.7784 |
    | GetCurFromPtr2 | 0.4638 | 0.4800 | 0.3950 | 0.4926 | 0.3956 || 0.4454 |
    |----------------+--------+--------+--------+--------+--------++--------|
    | ReturnThisByt1 | 0.8593 | 0.8589 | 0.8593 | 1.1777 | 0.8732 || 0.9257 |
    | ReturnThisByt2 | 0.4078 | 0.4972 | 0.5055 | 0.4036 | 0.4067 || 0.4442 |
    |                |        |        |        |        |        ||        |
    | ReturnThisInt1 | 0.8775 | 1.1676 | 1.1693 | 0.8591 | 0.8593 || 0.9866 |
    | ReturnThisInt2 | 0.3827 | 0.3854 | 0.3827 | 0.4069 | 0.3824 || 0.3880 |
    |                |        |        |        |        |        ||        |
    | ReturnThisLng1 | 0.6896 | 0.6774 | 0.6708 | 0.6756 | 0.6710 || 0.6769 |
    | ReturnThisLng2 | 0.3827 | 0.3871 | 0.3826 | 0.4969 | 0.3824 || 0.4063 |
    |                |        |        |        |        |        ||        |
    | ReturnThisCur1 | 0.7548 | 0.7372 | 0.7215 | 1.0280 | 1.0559 || 0.8595 |
    | ReturnThisCur2 | 0.4825 | 0.4212 | 0.4176 | 0.4159 | 0.5006 || 0.4476 |
    |----------------+--------+--------+--------+--------+--------++--------|
    | GetStrFromPtr1 | 9.8013 | 9.6432 | 9.5857 | 9.5942 | 9.9817 || 9.7212 |
    | GetStrFromPtr2 | 8.7456 | 8.7415 | 8.8219 | 8.6931 | 8.6676 || 8.7339 |
    |                |        |        |        |        |        ||        |
    | GetObjFromPtr1 | 2.2159 | 2.2174 | 2.2177 | 2.2180 | 2.2173 || 2.2173 |
    | GetObjFromPtr2 | 1.1721 | 1.1706 | 1.1718 | 1.1708 | 1.1720 || 1.1715 |
    |                |        |        |        |        |        ||        |
    | GetUDTFromPtr1 | 6.6959 | 6.8592 | 6.9498 | 6.4377 | 6.9515 || 6.7788 |
    | GetUDTFromPtr2 | 7.0108 | 6.6621 | 6.8581 | 6.5292 | 6.7746 || 6.7670 |
    +-----------------------------------------------------------------------+
    
    +------------------------------------------------------------------------------------+
    |        25,000         |   1st   |   2nd   |   3rd   |   4th   |   5th   ||   Ave.  |
    |-----------------------+---------+---------+---------+---------+---------++---------|
    | CopyOverlappingMemory | 13.2884 | 13.2909 | 13.4995 | 13.1313 | 13.1234 || 13.2667 |
    | CopyOverlappingBytes  | 13.4767 | 12.9320 | 13.1654 | 13.0970 | 13.0053 || 13.1353 |
    +------------------------------------------------------------------------------------+
    Judging from the above table, it appears that most of the alternative APIs perform the same task slightly faster than does CopyMemory. The only exception is with the CopyBytes (a.k.a. __vbaCopyBytes) API. It shouldn't be surprising though since, except for their parameter order, they basically work the same way. Their only difference, it seems, is in the way they handle overlapping blocks of memory. CopyBytes doesn't appear to take into account overlapping blocks when copying memory and thus corrupts data when going forward. CopyMemory, on the other hand, was designed to correctly handle this issue. That's most likely the reason for its slightly slower performance compared to the other APIs. Overlapping blocks of memory aren't usually encountered in the typical cases of memory copying, so for those interested in optimizing for speed, it would probably be better to call one or more of the relevant APIs shown above instead of the all-around CopyMemory API.
    Attached Files Attached Files
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

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

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    Quick question.

    Public Function GetStrFromPtrA(ByVal Ptr As Long) As String
    GetStrFromPtrA = SysAllocStringByteLen(Ptr, lstrlenA(Ptr))
    End Function

    Given your declaration does VB know to SysFreeString the BSTR returned by SysAllocStringByteLen, after it's Coverted to Unicode and copied to a new String? I can't help but think there's an inherent memory leak here. BSTR leaks are tough to track down considering OLE buffers String Allocation/Deallocation.

  5. #5

    Thread Starter
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    Quote Originally Posted by DEXWERX View Post
    ... does VB know to SysFreeString the BSTR returned by SysAllocStringByteLen, after it's Coverted to Unicode and copied to a new String?
    It apparently does:

    Name:  Process Hacker's Properties dialog box.png
Views: 5375
Size:  9.5 KB

    Code:
    Option Explicit
    
    Private Declare Function lstrlenA Lib "kernel32.dll" (ByVal lpString As Long) As Long
    Private Declare Function SysAllocStringByteLen Lib "oleaut32.dll" (Optional ByVal pszStrPtr As Long, Optional ByVal Length As Long) As String
    
    Private WithEvents cmdSmallBSTR As VB.CommandButton
    Private WithEvents cmdLargeBSTR As VB.CommandButton
    Private WithEvents cmdFreeBSTR  As VB.CommandButton
    
    Private m_BSTR As String
    
    Private Sub cmdFreeBSTR_Click()
        m_BSTR = vbNullString
        Caption = """" & m_BSTR & """"
    End Sub
    
    Private Sub cmdLargeBSTR_Click()
        Dim I As Long, T As Single, Spaces As String
    
        T = Timer
            Spaces = Space$(&H100000) '2 MB
    
            For I = 1& To 1000&
                m_BSTR = GetStrFromPtrA(StrPtr(StrConv(Spaces & CStr(I), vbFromUnicode)))
            Next
        T = Timer - T
    
        Caption = """..." & Right$(m_BSTR, 10&) & """"
        MsgBox T & " seconds", vbInformation
    End Sub
    
    Private Sub cmdSmallBSTR_Click()
        Dim I As Long, T As Single
    
        T = Timer
            For I = 1& To 1000000
                m_BSTR = GetStrFromPtrA(StrPtr(StrConv(CStr(I), vbFromUnicode)))
            Next
        T = Timer - T
    
        Caption = """" & m_BSTR & """"
        MsgBox T & " seconds", vbInformation
    End Sub
    
    Private Sub Form_Load()
        Set cmdSmallBSTR = Controls.Add("VB.CommandButton", "cmdSmallBSTR")
        Set cmdLargeBSTR = Controls.Add("VB.CommandButton", "cmdLargeBSTR")
        Set cmdFreeBSTR = Controls.Add("VB.CommandButton", "cmdFreeBSTR")
    
        cmdSmallBSTR.Caption = "&Small BSTR":   cmdSmallBSTR.Visible = True
        cmdLargeBSTR.Caption = "&Large BSTR":   cmdLargeBSTR.Visible = True
        cmdFreeBSTR.Caption = "&Free BSTR":     cmdFreeBSTR.Visible = True
    
        ScaleMode = vbPixels
    End Sub
    
    Private Sub Form_Resize()
        Const GAP = 5!, HALF = 0.5!
        Dim sngWidth As Single, sngTop As Single
    
        On Error Resume Next
        sngWidth = cmdSmallBSTR.Width
        sngTop = (ScaleHeight - cmdSmallBSTR.Height) * HALF
    
        cmdSmallBSTR.Move (ScaleWidth - (sngWidth * 3! + GAP * 2!)) * HALF, sngTop
        cmdLargeBSTR.Move cmdSmallBSTR.Left + sngWidth + GAP, sngTop
        cmdFreeBSTR.Move cmdLargeBSTR.Left + sngWidth + GAP, sngTop
    End Sub
    
    Private Function GetStrFromPtrA(ByVal Ptr As Long) As String
        GetStrFromPtrA = SysAllocStringByteLen(Ptr, lstrlenA(Ptr))
    End Function


    Maybe someone who has sufficient experience in disassembling VB6 code can present a more conclusive proof...
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

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

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    That's awesome. I would think the runtime would check where the "String" is being returned from and do either a LocalFree or a SysFreeString for OLEAUTO APIs.
    Would hate to bug Trick or someone else but my curiosity may force my hand.

  7. #7

  8. #8

    Thread Starter
    Default Member Bonnie West's Avatar
    Join Date
    Jun 2012
    Location
    InIDE
    Posts
    4,060

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    Thanks a lot for the confirmation, The trick!
    On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
    Declare Sub CrashVB Lib "msvbvm60" (Optional DontPassMe As Any)

  9. #9
    New Member
    Join Date
    Apr 2017
    Posts
    4

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    Is there any way to access these GetMemx/PutMemx functions from VBA7? I can't seem to reference the MSVBVM60 dll and haven't found a workaround...

  10. #10
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,904

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    Normally the VB6 runtime DLL is available on all Windows versions since WinXP.

    But why do you want to use these techniques from VBA7?

  11. #11
    New Member
    Join Date
    Apr 2017
    Posts
    4

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    I want to test dereferencing pointers using GetMemx v RtlMoveMemory as the benchmarks suggest a considerable performance improvement.

    I wanted to add the following clarfication to my 1st post, but couldn't see how to edit:

    I am running VBA7 on Windows 8.1 64-bit - when I try to add a reference to c:\Windows\SysWOW64\msvbvm60.dll I get the following error: "Name conflicts with existing module, project or object library".

    There's a similar question on Stackflow - http://stackoverflow.com/questions/1...om-64-bit-code - which suggests that it can't be done. Is this true?

  12. #12
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,904

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    The performance gain is not that big, not even 0.5s for 10.000.000 calls.

    You don't have to add a reference. Just use the Declare statements.
    Or are you also using Office 64 bit?

  13. #13
    New Member
    Join Date
    Apr 2017
    Posts
    4

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    I understand. But for 100mn+ calls in a time-critical application, the potential saving of 5+ secs is of interest to me.

    And yes, I'm using 64-bit Office. Thanks

  14. #14
    PowerPoster Arnoutdv's Avatar
    Join Date
    Oct 2013
    Posts
    5,904

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    VBA7 64bit is a different beast compared to 32bit VB6.
    https://msdn.microsoft.com/en-us/lib...ffice.14).aspx

  15. #15
    New Member
    Join Date
    Apr 2017
    Posts
    4

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    Ok - here's what I've done:

    1. Installed 32-bit Office, run a comparison of GetMemx versus CopyMemory and confirmed that GetMem completes in roughly half the time - 344msec v 580msec. The bare loop takes 120msec so GetMemx took 224 and CopyMemory 460 respectively.

    2. Re-installed 64-bit Office, ran the same test (a for loop) using CopyMemory and saw this take 14440 msec !! Repeated the test several times, re-booted the computer and still the same amount of time give or take a few msecs.

    Any idea why CopyMemory/RtlMoveMemory would so much slower in 64-bit Office?

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

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    You can compile your own version of GetMemX in a 64bit dll if you really want, but i suspect 64bit office is just slow calling APIs.

    This is just one of the many reasons corporate IT dept's use 32bit office as a standard.

    edit: post your code, and I bet we can speed it up. Also I bet you can get Array Mapping working in 64bit VBA.


    edit 2: I've attached my AryMap Class, for use in VBA. No guarantees but it should work in 64bit VBA as well.
    Since you can't use the typelib, you'll need the following API's.
    I don't know of an equivelent 64bit VarPtrStringArray() function, but VarPtrArray should work with all other array types.
    I've also shown how to spoof the underlying pointers of ByRef parameters.
    Should be enough food for thought.

    edit 3: It seems MS has fixed / removed the automatic unicode to ansi conversion when grabbing the pointer to an Array Variable. slightly jealous

    Code:
    Option Compare Database
    Option Explicit
    
    Public Declare PtrSafe Function Ref Lib "vbe7" Alias "VarPtr" (ByRef Ptr As Any) As LongPtr
    Public Declare PtrSafe Function RefAry Lib "vbe7" Alias "VarPtr" (ByRef Var() As Any) As LongPtr
    Public Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As LongPtr)
    Public Const vbNullPtr As LongPtr = 0&
    Public Property Get DeRef(ByVal Address As LongPtr) As LongPtr
        CopyMemory DeRef, ByVal Address, LenB(DeRef)
    End Property
    Public Property Let DeRef(ByVal Address As LongPtr, ByVal Value As LongPtr)
        CopyMemory ByVal Address, Value, LenB(Value)
    End Property
    
    Sub Testing(Optional ByVal Dummy As LongPtr, _
                Optional ByRef Mem2 As Integer, _
                Optional ByRef Mem4 As Long)
    
        Dim s As String: s = "TEST STRING. "
        Dim s2 As String: s2 = "The Answer is  "
        
        Dim Chars() As Integer
        With AryMap(RefAry(Chars), StrPtr(s), 2, 32, 1) ' 32 is an arbitrary length...
            Chars(5) = AscW("_")
            Chars(9) = AscW("!")
            
            .BasePtr = StrPtr(s2)
            Chars(15) = AscW(":")
        End With
        
        Dim MyLong As Long
        MyLong = 7
        
        Dim Ptr(1 To 2) As LongPtr ' You can use a whole array of pointers and do a single CopyMem, to lessen the API overhead
        Ptr(1) = StrPtr(s) + LenB(Mem2) * (4 - 1) ' Reference to 4th Character
        Ptr(2) = Ref(MyLong)
        
        'Copy pointers to stack
        CopyMemory ByVal Ref(Dummy) + LenB(Dummy), Ptr(1), LenB(Dummy) * UBound(Ptr)
        
        Mem2 = AscW("#")
        Mem4 = Mem4 * 6
        
        MsgBox s & s2 & MyLong
    End Sub
    
    Sub Testing2()
        Testing
    End Sub
    Attached Files Attached Files
    Last edited by DEXWERX; May 1st, 2017 at 10:50 AM.

  17. #17
    Fanatic Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    678

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    Hi
    I need to copy 2D arrays of singles from one variable to another.
    With CopyMemory I have no problems and I know how.
    I wonder if it can be done with GetMem4 (PutMem4) in order to speed up the operation.

    Or more generally is it possible to copy an array faster than copymemory?

  18. #18

  19. #19
    Fanatic Member
    Join Date
    Sep 2010
    Location
    Italy
    Posts
    678

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    Quote Originally Posted by The trick View Post
    reexre,
    do you need the copy (to have 2 identical arrays) or you need to move from a variable to another, or map a array variable to other?
    I need to copy (to have 2 identical arrays)

  20. #20

  21. #21

  22. #22
    PowerPoster
    Join Date
    Jan 2020
    Posts
    3,749

    Re: [VB6] Dereferencing Pointers sans CopyMemory

    how to use SetStrToPtr(string1 as string,Ptr as long) by heap?

    Code:
    Private Declare Function SysReAllocString Lib "oleaut32.dll" (ByVal pBSTR As Long, Optional ByVal pszStrPtr As Long) As Long
    Public Function GetStrFromPtrw(ByVal Ptr As Long) As String
        'GOOD
        SysReAllocString VarPtr(GetStrFromPtrw), Ptr
    End Function
    
    Function NewStringPtr(Str1 As String) As Long
        '把字符串存到堆内存里
        Dim Ptr As Long, Size As Long
        Size = LenB(Str1) + 6 '4字节长度+2字节空白
        Ptr = HeapAlloc(GetProcessHeap, HEAP_NO_SERIALIZE, Size)
         memcpy ByVal Ptr, ByVal StrPtr(Str1) - 4, LenB(Str1) + 6 '多加2字节
         NewStringPtr = Ptr
    End Function

Tags for this Thread

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