Byref Explained
by
, 12-Oct-2009 at 08:00 AM (4206 Views)
Pointer, byref, AddressOf(), what's the difference between byref and Pointer anyway? If you know C++ you might say that by-reference is semantically very similar to a pointer but with different syntax. In Visual DataFlex, byref and pointer are actually used for different purposes.
This is best illustrated with String, consider the following code:
If you compile and run this code you'll of course see that it works, after the call to Foo, sData contains the modified value "Goodbye". If you'd try this with pointers it might look something like this:Code:Use DfAllEnt.pkg Procedure Foo String byref sData Move "Goodbye" to sData End_Procedure Procedure TestIt String sData Move "Hello" to sData Showln "Before: " sData Send Foo (&sData) Showln "After: " sData End_Procedure Send TestIt inkey windowindex
Clearly this is more complicated and error prone, but not only that, if you compile and run it you'll find that it actually doesn't even work. You may even find that it crashes, or that it truncates the string to "Goodb", or behaves in other very strange ways.Code:Procedure Foo Pointer pData String sNewData Boolean bOk Move "Goodbye" to sNewData //ERROR - The following will not work correctly if the buffer //represented by pData is not large enough Move (MemCopy(pData,AddressOf(sNewData),Length(sNewData))) to bOk End_Procedure Procedure TestIt String sData Move "Hello" to sData Showln "Before: " sData Send Foo (AddressOf(sData)) Showln "After: " sData End_Procedure
The reason for this difference in behavior lies in the details of the String datatype. A String is implemented as a sequence of characters, where each character is represented by a byte. The memory allocated by a String is dynamic, and the size grows with the length of the string. Of course, you never have to bother with the internal details of memory allocations for String, it's taken care of automatically. So the String variable holds two pieces of information, the length of the string and a pointer to the memory allocated for the string with the actual value. Of course, this is an internal implementation detail, and no external code can be expected to know the internal structure of a VDF String variable. However, the general idea of a sequence of bytes representing the string value is universal.
So you can pass a pointer to the sequence of bytes in memory, and chances are that you can read and manipulate the value in whatever other language you're using in that DLL. But you're limited to just reading and writing to the already allocated sequence of bytes. If you need to store a longer string, you're out of luck as that would require allocating more memory, and you have no way of informing the VDF code that it should now refer to a different chunk of memory(given only the pointer).
The AddressOf() function is designed to return a C-style compatible pointer to the value of the variable, primarily for use with external code such as DLL calls. Whereas byref is designed to pass an internal reference to the variable, so that other VDF code can modify the value as if it had direct access to the actual variable.
Now you can see that AddressOf() returns the C-style pointer to the sequence of characters in the string, and that you cannot modify the length of the buffer. That's why the code above using AddressOf() and pointers doesn't work. The string "Goodbye" is longer than "Hello", but the code doesn't take that into account, and there would be no way to do so as it can't reallocate the buffer.
When using byref on the other hand, the system can take advantage of the fact that it's all Visual DataFlex code, and it can pass around internal references to the actual String variable directly, instead of a crude pointer to a sequence of characters. And because it's a reference to a variable, the code can modify it just like any other variable, and the String can grow in size as needed.
So, byref is not the same as AddressOf() and Pointer. AddressOf() should be used when calling external code in DLLs, and byref should be used for VDF code as it provides much greater flexibility and is easier to use.