I've run across this "Incompatible types" error in the comment below a few times, and never been happy with why this isn't directly supported in Delphi 2007:
program Project1; {$APPTYPE CONSOLE}
type TCharArray = array of Char;
procedure DoArray(Chars: array of Char);
begin
end;
function ReturnTCharArray: TCharArray;
var CharArray: TCharArray;
begin
Result := CharArray;
end;
begin
DoArray(ReturnTCharArray); // [DCC Error] Project1.dpr(18): E2010 Incompatible types: 'Array' and 'TCharArray'
end.
Shouldn't it be possible to make an array type "aliased" to another array type compatible with each other? Assuming I can't change the declaration of DoArray (it is part of a third party library), how do I write a function returning an array of char compatible with DoArray's param? The straightforward "function ReturnAChar: array of Char;" results in an "Identifier expected but 'ARRAY' found" error. I even tried changing the function returning the array to a procedure with a var "array of Char" pram, but that also doesn't allow setting the length of the "array of Char" param in the procedure ("Constant object cannot be passed as var parameter").
This may actually be a compiler bug (or a limitation that was never documented properly). I did some experimentation and found that you can pass a dynamic array (typed or not) to a procedure expecting an open array for almost every type... except Char and WideChar.
See Is a dynamic array of Char allowed when the parameter type is open array of Char? for a description of the problem and a possible work around.
When typed @ operator is off the compiler does not check what you assign to a pointer, so you can call a procedure with wrong parameters:
program Project1; {$APPTYPE CONSOLE}
type TCharArray = array of Char;
procedure DoArray(Chars: array of Char);
begin
end;
function ReturnTCharArray: TCharArray;
var CharArray: TCharArray;
begin
Result := CharArray;
end;
type TFakeDoArray = procedure(Chars: TCharArray);
var
FakeDoArray: TFakeDoArray;
begin
FakeDoArray := @DoArray;
FakeDoArray(ReturnTCharArray);
end.
While the compiler won't complain, for the very reason 'Jeroen' indicates in his comment for Mason's answer, this will not work.
You can then try declaring your fake procedure compatible with one with an open array parameter:
program Project1; {$APPTYPE CONSOLE}
type TCharArray = array of Char;
procedure DoArray(Chars: array of Char);
begin
end;
function ReturnTCharArray: TCharArray;
var CharArray: TCharArray;
begin
Result := CharArray;
end;
type
TFakeDoArray = procedure(AnArray: Pointer; High: Integer);
var
FakeDoArray: TFakeDoArray;
Tmp: TCharArray;
begin
FakeDoArray := @DoArray;
Tmp := ReturnTCharArray;
FakeDoArray(Tmp, High(Tmp));
end.
Credits are due Rudy for his great article. And the relevant documentation (from Program Control):
An open-array parameter is passed as
two 32-bit values. The first value is
a pointer to the array data, and the
second value is one less than the
number of elements in the array.
You don't. Pascal handles array types by name, not by description, and always has. Why can't you change the declaration of DoArray? (And why was it written like that in the first place?)
One point that I didn't see mentioned yet is that TCharArray is a dynamic array type, while in
procedure DoArray(Chars: array of Char);
Chars is an open array parameter. There is no syntax to declare a dynamic array parameter. To have a dynamic array parameter, it needs to be declared as a type.
type
TMyDynArray = array of Integer;
procedure DoArray(Integers : TMyDynArray);