|
-
Jan 14th, 2006, 10:48 AM
#1
Thread Starter
Member
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.
-
Jan 15th, 2006, 11:22 AM
#2
Re: What's all the fuss about COPYMEMORY ?
where is the fuss besides here?
-
Jan 15th, 2006, 11:32 AM
#3
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
-
Mar 20th, 2006, 10:24 PM
#4
Fanatic Member
Re: What's all the fuss about COPYMEMORY ?
CopyMemory is used to create basic structures such as stacks, queues, and linked lists.
-
Mar 22nd, 2006, 05:56 AM
#5
Frenzied Member
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:
[dllname("msvbvm60.dll")]
module VirtualMachine
{
[entry("GetMem4"),propget]
HRESULT MemLong ([in] long Address,[out,retval]long* Value);
[entry("PutMem4"),propput]
HRESULT MemLong ([in] long Address,[in] long Value);
}
This allows the following:
VB Code:
Dim lp As Long
Dim l As Long
l = MemLong(lp)
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
-
Mar 22nd, 2006, 06:10 AM
#6
Frenzied Member
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:
Option Explicit
'Public Type MATRIX_HEADER
' i As Long 'Offset:0
' j As Long 'Offset:4
' Size As Long 'Offset:8
' hHeap As Long 'Offset:12
'End Type
Public Function MCreate(i As Long, j As Long) As Long
On Error GoTo ERR_MCreate
Dim HeaderSize As Long
Dim pHeap As Long
Dim hHeap As Long
Dim Size As Long
'******************************
'* Get the required sizes . . .
'******************************
Size = i * j * 4
'**********************
'* Get the memory . . .
'**********************
hHeap = HeapCreate(HEAP_GENERATE_EXCEPTIONS, 16 + Size, 0)
pHeap = HeapAlloc(hHeap, HEAP_GENERATE_EXCEPTIONS, Size)
'********************************
'* Write the header records . . .
'********************************
MemLong(pHeap) = i
MemLong(pHeap + 4) = j
MemLong(pHeap + 8) = Size
MemLong(pHeap + 12) = hHeap
'********************************************
'* Return pointer to start of structure . . .
'********************************************
MCreate = pHeap
Exit Function
ERR_MCreate:
Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
End Function
Public Sub MDestroy(pMatrix As Long)
On Error GoTo ERR_MDestroy
Dim hHeap As Long
'*************************************************************************
'* Derference the matrix header's heap record, and release the heap . . .
'*************************************************************************
hHeap = MemLong(pMatrix + 12)
HeapDestroy hHeap
Exit Sub
ERR_MDestroy:
Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
End Sub
Public Function MSMultiply(Scalar As Single, pMatrix As Long) As Long
On Error GoTo ERR_MSMultiply
Dim pMem1 As Long
Dim pMem2 As Long
Dim pMatrix2 As Long
Dim i As Long
Dim j As Long
Dim s As Long
'******************************************
'* Get start of memory block and size . . .
'******************************************
pMem1 = pMatrix + 16
s = MemLong(pMatrix + 8)
'*************************************************************
'* Copy dimensions of source matrix, and use 'em for the return
'* one . . .
'*************************************************************
i = MemLong(pMatrix)
j = MemLong(pMatrix + 4)
pMatrix2 = MCreate(i, j)
pMem2 = pMatrix + 16
'****************************
'* Perform the multiply . . .
'****************************
For i = 0 To s Step 4
MemSingle(pMem2 + i) = (MemSingle(pMem1 + i) * Scalar)
Next
'************************************
'* Return pointer to new matrix . . .
'************************************
MSMultiply = pMatrix2
Exit Function
ERR_MSMultiply:
Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext
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:
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, source As Any, ByVal Length As Long)
Public Type SafeArray1d
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
cElements As Long
lLbound As Long
End Type
Public Const ARRAY_NOT_INITIALISED As Long = -1
Public Function MaxOrdinal(ppSA As Long) As Long
' Eg: n = MaxOridinal(VarPtrArray(MyArray))
Dim SA As SafeArray1d
Dim pSA As Long
'***********************************************
'* Deref ppSA. C equivalent: = pSa=*ppSA . . .
'***********************************************
CopyMemory pSA, ByVal ppSA, 4
'*****************************************************
'* If we have a pointer then check to see how
'* many elements we are allowed. If the array
'* is not dimensioned then pSA will not be valid . . .
'*****************************************************
If pSA Then
CopyMemory SA, ByVal pSA, LenB(SA)
MaxOrdinal = (SA.cElements - 1)
Else
MaxOrdinal = ARRAY_NOT_INITIALISED
End If
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|