iNET Interactive - Online Advertising Agency
          
Go Back  Xtreme Visual Basic Talk > Other Languages > Miscellaneous Languages > ByVal vs. ByRef arguments when using RtlMemoryMove in VB


Reply
 
Thread Tools Display Modes
  #1  
Old 01-17-2003, 06:23 AM
grossd
 
Posts: n/a
Default ByVal vs. ByRef arguments when using RtlMemoryMove in VB

Hello,

In my VB program i am retrieving several fields from a C struct whose pointer i have stored in a long variable, i have two different parameter passing usages for RtlMoveMemory, and was wondering, why they work?

First i have the two declarations:

Declare Sub RtlMoveMemory Lib "kernel32.dll" _
(ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long)

Declare Sub Peek Lib "kernel32" Alias "RtlMoveMemory" ( _
nDest As Any, _
ByVal lpSrc As Long, _
ByVal nLen As Long _
)

Note that "Peek"'s first argument is NOT byVal:

In C i have the following struct:

struct answer {
char* sender;
int completion;
char* return_data;
}

and in VB i have the following declaration

Public Type Answer
sender As String
Completion As Long
return_data As String
End Type


In my VB code i first receive a pointer to this struct from an external C DLL:

Declare Function askCB Lib "D:\libs\libcb.dll" _
(ByVal Server As String) As Long


Dim pAnswer as long
pAnswer = askCB("MyServer")

Once received the pointer to an answer struct in pAnswer i calculate the memory locations of each string field in the Answer struct, and retrieve the completion value also.

Dim pSender As Long
Dim Completion As Long
Dim pReturn_data As Long

Call Peek(pSender, ByVal ansHandle, 4)
Call Peek(Completion, ByVal ansHandle + 4, 4)
Call Peek(pReturn_data, ByVal ansHandle + 8, 4)


I then retrieve the actual strings stores in memory:

Dim l As Integer
dim anAnswer as Answer


l = lstrlen(pSender)

anAnswer.sender = Space$(l + 1)
RtlMoveMemory ByVal anAnswer.sender, ByVal pSender, l

l = lstrlen(pReturn_data)
anAnswer.return_data = Space$(l + 1)
RtlMoveMemory ByVal anAnswer.return_data, ByVal pReturn_data, l


using lstrlen which is:

Public Declare Function lstrlen Lib "kernel32" _
(ByVal lpSrc As Long) As Long


Now here is the key difference:

Peek does NOT pass its first parameter byVal while RtlMoveMemory does. When changing Peeks' first argument to passing ByVal (both in the declare and the function call) the VB program crashes.

So i was wondering, what is the difference between these two usages of the same underlying kernel function.


appreciating any help

Daniel
Reply With Quote
  #2  
Old 01-17-2003, 05:07 PM
OnErr0r's Avatar
OnErr0r OnErr0r is offline
Obsessive OPtimizer
Administrator
* Guru *
 
Join Date: Jun 2002
Location: Debug Window
Posts: 13,073
Default

I always use one Declare for RtlMoveMemory for all purposes. Creating a declare with an alias and specific param types is called a Type Safe declare. Personally I find it unnecessary. More declares just take more space in the EXE.

Declare Sub RtlMoveMemory Lib "kernel32.dll" _
(ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

Since the first two params are ByRef As Any, you are allowed to pass anything as an argument. It is not necessary to alter this declare, only specify ByVal for certain arguments. You must understand what you are passing to avoid problems.

If you plan to pass a pointer, you must pass it ByVal:

Code:
Dim b() As Byte Redim b(3) RtlMoveMemory b(0), ByVal lPointer, 4

That would pass the value of the pointer (address) and copy 4 bytes at that address into a byte array.

If you're copying a pointer into a string, you must buffer the string first and pass it ByVal. VB will convert the ansi string to unicode and copy it into the string. If you'd rather copy unicode data directly into the unicode BSTR in VB, use ByVal StrPtr(s).

Code:
RtlMoveMemory ByVal s, ByVal lPointer, Len(s)

To sum it up, ByRef passes the address of something, usually a struct or first item of an array. ByVal is to pass a pointer or string buffer.
__________________
Quis custodiet ipsos custodues.
Reply With Quote
  #3  
Old 01-18-2003, 05:18 PM
grossd
 
Posts: n/a
Default

i have tried to use the "generic" RtMoveMemory with a VB type


Declare Sub RtlMoveMemory Lib "kernel32.dll" _
(ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)

Public Type Answer
sender As String
Completion As Long
return_data As String
End Type


Dim theAnswer As Answer

RtlMoveMemory theAnswer, ByVal ansHandle, 12

but i got a "Bad DLL Calling Convention Error" ...

Why did this happen?

BTW when using:

Call Peek(theAnswer, ansHandle, 12)

it worked fine, (BTW, even the strings included in the Type seem properly converted from ANSI to Unicode).


pss. In the Call Peek example, does VB free the ANSI strings buffers that held the ANSI strings included in the Answer struct that were allocated prior within the external DLL? Also, did VB free the Answer struct also (the two pointers to the ANSI string buffers and the Completion int)?

or does the Answer struct within the DLL still need to be freed (deallocated)?
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Forum Jump

Advertisement: