I wrote two methods with a void type parameter:
procedure Method1(const MyVar; size: cardinal);
var
Arr: array of byte;
begin
SetLength(Arr, size);
{now copy the data from MyVar to Arr, but how?}
end;
procedure Method2(var MyVar; size: cardinal);
var
Arr: array of byte;
begin
SetLength(Arr, size);
{return the data from the array, but how?}
end;
In the first one I would like to access the MyVar as an array of byte. In the second one, I would like to copy the data from the local array Arr to MyVar. Therefore I used the CopyMemory() function, but something is wrong with it.
If I use the following in the second method, it is fine as long as Method2 is called with an array as its parameter (Method2(Pointer(MyString)^, Length(MyString)) or Method2(Pointer(MyArray), Length(MyArray))).
CopyMemory(Pointer(MyVar), Pointer(Arr), size);
If I call Method2 with a, for instance, integer parameter (Method2(MyInteger, SizeOf(MyInteger))), it does not work properly. In this case, the CopyMemory() has to be called this way:
CopyMemory(@MyVar, Pointer(Arr), size);
How to return data from Method2 correctly not knowing whether it is a simple type (or record) or an array? The situation will be similar in Method1, but here I would have to use
CopyMemory(Pointer(Arr), Pointer(MyVar), size);
in case of arrays and
CopyMemory(Pointer(Arr), @MyVar, size);
in case of simple types.
What can I do about it when I don’t know what the MyVar parameter is?
There’s no such thing a a void type in Delphi. What you’re referring to is called an untyped parameter.
An untyped parameter is always the actual thing itself, not a pointer to the thing you’re supposed to use. Therefore, the correct way to use
CopyMemorywith such a parameter is to apply the@operator to it, like so:Notice I’ve also changed the way I pass the second parameter. It’s better if you don’t rely on the fact that a dynamic array is really a pointer to the first element. If you need a pointer to the first element, just say so explicitly, like I did here.
Your confusion comes from a test you made where the parameter was used as though it were a pointer, and the test appeared to work. I doubt the validity of that test, though. When you said
Pointer(MyString)^, what you had was the first character of the string. When you then saidPointer(MyVar)inside the function, you were type-casting that character into a pointer, which was an invalid type-cast. If your program appeared to work, then it was only by accident; your code was wrong.The best advice I can give is to not type-cast stuff unless you really have to. And when you do, please be sure that the thing you’re type-casting really does have that type. In your case, you don’t need to type-cast anything before you pass it as an untyped parameter. You can call
Method1like this:(I multiply by
SizeOf(Char)since I don’t know whether you have Delphi 2009 or not.)Also, do avoid untyped parameters. One of the great things a compiler can do to help ensure program correctness is to enforce type safety, but when you take away the types, the compiler can’t help you anymore.