Results 1 to 6 of 6

Thread: What's all the fuss about COPYMEMORY ?

  1. #1

    Thread Starter
    Member
    Join Date
    Dec 2005
    Posts
    43

    What's all the fuss about COPYMEMORY ?

    Hi there,

    Can anybody show a practical real-world use for the CopyMemory API in VB apart from simply copying memory bits to an array ?

    I still don't really understand all the fuss about this function .

    Thanks in advance.

  2. #2
    Old Member moeur's Avatar
    Join Date
    Nov 2004
    Location
    Wait'n for Free Stuff
    Posts
    2,712

    Re: What's all the fuss about COPYMEMORY ?

    where is the fuss besides here?

  3. #3
    The Devil crptcblade's Avatar
    Join Date
    Aug 2000
    Location
    Quetzalshacatenango
    Posts
    9,091

    Re: What's all the fuss about COPYMEMORY ?

    You use CopyMemory to convert a pointer into a UDT for many APIs.
    Laugh, and the world laughs with you. Cry, and you just water down your vodka.


    Take credit, not responsibility

  4. #4
    Fanatic Member VBAhack's Avatar
    Join Date
    Dec 2004
    Location
    Sector 000
    Posts
    617

    Re: What's all the fuss about COPYMEMORY ?

    CopyMemory is used to create basic structures such as stacks, queues, and linked lists.

  5. #5
    Frenzied Member yrwyddfa's Avatar
    Join Date
    Aug 2001
    Location
    England
    Posts
    1,253

    Re: What's all the fuss about COPYMEMORY ?

    VB, generally, does not allow direct access to memory. This can be prohibitively slow - in some cases - so some programmers prefer to get dirty and get down to the details to provide a (sometimes) huge increase in performance.

    In many cases CopyMemory is used to dereference a pointer (as described above) but this is mostly unecessary.

    For instance you can use IDL (to create a typelibrary) and squeeze implied semantic functionality from a few other 'unknown' functions:

    VB Code:
    1. [dllname("msvbvm60.dll")]
    2.     module VirtualMachine
    3.     {
    4.         [entry("GetMem4"),propget]
    5.         HRESULT MemLong ([in] long Address,[out,retval]long* Value);
    6.         [entry("PutMem4"),propput]
    7.         HRESULT MemLong ([in] long Address,[in] long Value);
    8.     }

    This allows the following:

    VB Code:
    1. Dim lp As Long
    2.     Dim l As Long
    3.    
    4.     l = MemLong(lp)
    5.     MemLong(lp) = l

    . . . which allows for more natural dereferencing code (and it's much MUCH) faster.

    I think that CopyMemory is so popular is because it's simply that it's so well known.
    Last edited by yrwyddfa; Mar 22nd, 2006 at 06:12 AM.
    "As far as the laws of mathematics refer to reality, they are not certain; and as far as they are certain, they do not refer to reality." - Albert Einstein

    It's turtles! And it's all the way down

  6. #6
    Frenzied Member yrwyddfa's Avatar
    Join Date
    Aug 2001
    Location
    England
    Posts
    1,253

    Re: What's all the fuss about COPYMEMORY ?

    For instance, consider the following VB code (it won't run - if you want to play I can provide a link to the project)

    VB Code:
    1. Option Explicit
    2.  
    3. 'Public Type MATRIX_HEADER
    4. '    i As Long               'Offset:0
    5. '    j As Long               'Offset:4
    6. '    Size As Long            'Offset:8
    7. '    hHeap As Long           'Offset:12
    8. 'End Type
    9.  
    10. Public Function MCreate(i As Long, j As Long) As Long
    11.  
    12.     On Error GoTo ERR_MCreate
    13.  
    14.     Dim HeaderSize As Long
    15.     Dim pHeap As Long
    16.     Dim hHeap As Long
    17.     Dim Size As Long
    18.    
    19.     '******************************
    20.     '* Get the required sizes . . .
    21.     '******************************
    22.     Size = i * j * 4
    23.  
    24.     '**********************
    25.     '* Get the memory . . .
    26.     '**********************
    27.     hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 16 + Size, 0)
    28.     pHeap = HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS, Size)
    29.    
    30.     '********************************
    31.     '* Write the header records . . .
    32.     '********************************
    33.     MemLong(pHeap) = i
    34.     MemLong(pHeap + 4) = j
    35.     MemLong(pHeap + 8) = Size
    36.     MemLong(pHeap + 12) = hHeap
    37.    
    38.     '********************************************
    39.     '* Return pointer to start of structure . . .
    40.     '********************************************
    41.     MCreate = pHeap
    42.    
    43.     Exit Function
    44.    
    45. ERR_MCreate:
    46.     Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
    47. End Function
    48.  
    49. Public Sub MDestroy(pMatrix As Long)
    50.  
    51.     On Error GoTo ERR_MDestroy
    52.    
    53.     Dim hHeap As Long
    54.    
    55.     '*************************************************************************
    56.     '* Derference the matrix header's heap record, and release the heap . . .
    57.     '*************************************************************************
    58.     hHeap = MemLong(pMatrix + 12)
    59.     HeapDestroy hHeap
    60.    
    61.     Exit Sub
    62.    
    63. ERR_MDestroy:
    64.     Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
    65. End Sub
    66.  
    67. Public Function MSMultiply(Scalar As Single, pMatrix As Long) As Long
    68.  
    69.     On Error GoTo ERR_MSMultiply
    70.  
    71.     Dim pMem1 As Long
    72.     Dim pMem2 As Long
    73.     Dim pMatrix2 As Long
    74.     Dim i As Long
    75.     Dim j As Long
    76.     Dim s As Long
    77.    
    78.     '******************************************
    79.     '* Get start of memory block and size . . .
    80.     '******************************************
    81.     pMem1 = pMatrix + 16
    82.     s = MemLong(pMatrix + 8)
    83.    
    84.     '*************************************************************
    85.     '* Copy dimensions of source matrix, and use 'em for the return
    86.     '* one . . .
    87.     '*************************************************************
    88.     i = MemLong(pMatrix)
    89.     j = MemLong(pMatrix + 4)
    90.     pMatrix2 = MCreate(i, j)
    91.     pMem2 = pMatrix + 16
    92.    
    93.     '****************************
    94.     '* Perform the multiply . . .
    95.     '****************************
    96.     For i = 0 To s Step 4
    97.         MemSingle(pMem2 + i) = (MemSingle(pMem1 + i) * Scalar)
    98.     Next
    99.    
    100.     '************************************
    101.     '* Return pointer to new matrix . . .
    102.     '************************************
    103.     MSMultiply = pMatrix2
    104.    
    105.     Exit Function
    106.    
    107. ERR_MSMultiply:
    108.     Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
    109. End Function

    This avoids many VB things that could be considered slow. To be fair, you'd probably want to write this lot in C and implement it in a DLL that VB can access: I only wrote this to play with the MemLong function (and to test it's speed)

    This fragment avoids SAFEARRAY overheads, and other VB safety features by directly allocating some memory, and then manipulating it according to various matrix rules. SAFEARRAYS are not great for dealing across different threads in a process with such wonderful features such as cbLocks in it's descriptor, and the automatic teardown code that goes with SAFEARRAYS (which, btw, makes VB marvellously simple and safe for beginners and experts alike)

    Also, ideally, the memory needs to be allocated on the stack, rather than the heap, but - hey: one step at a time.

    It also creates a completly arbitrary descriptor (I invented it, if you like) to describe the matrix structure. Which means the thread only needs to have a copy of the descriptor, and not the body of data. You can effectively pass around the descriptor instead of the data.

    You can replace the vast majority of MemLong, and MemSingle calls in this fragment with CopyMemory calls - so hopefully you can see the advantage in using it. Normally, though, you'd be using CopyMemory to directly access parts of VB's internal system as in this example:

    VB Code:
    1. Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, source As Any, ByVal Length As Long)
    2.  
    3. Public Type SafeArray1d
    4.     cDims As Integer
    5.     fFeatures As Integer
    6.     cbElements As Long
    7.     cLocks As Long
    8.     pvData As Long
    9.     cElements As Long
    10.     lLbound As Long
    11. End Type
    12.  
    13. Public Const ARRAY_NOT_INITIALISED As Long = -1
    14.  
    15. Public Function MaxOrdinal(ppSA As Long) As Long
    16.    
    17.     ' Eg: n = MaxOridinal(VarPtrArray(MyArray))
    18.    
    19.     Dim SA As SafeArray1d
    20.     Dim pSA As Long
    21.  
    22.     '***********************************************
    23.     '* Deref ppSA. C equivalent: = pSa=*ppSA . . .
    24.     '***********************************************
    25.     CopyMemory pSA, ByVal ppSA, 4
    26.    
    27.     '*****************************************************
    28.     '* If we have a pointer then check to see how
    29.     '* many elements we are allowed. If the array
    30.     '* is not dimensioned then pSA will not be valid . . .
    31.     '*****************************************************
    32.     If pSA Then
    33.         CopyMemory SA, ByVal pSA, LenB(SA)
    34.         MaxOrdinal = (SA.cElements - 1)
    35.     Else
    36.         MaxOrdinal = ARRAY_NOT_INITIALISED
    37.     End If
    38.    
    39. End Function

    which returns the highest ordinal allocated in an a single dimensional array, and ARRAY_NOT_INITIALISED if the array is not allocated yet; this is incredibly useful in production code, as well as being extremely fast.
    Last edited by yrwyddfa; Mar 22nd, 2006 at 06:19 AM.
    "As far as the laws of mathematics refer to reality, they are not certain; and as far as they are certain, they do not refer to reality." - Albert Einstein

    It's turtles! And it's all the way down

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