Question

Var
     A : Array [1..4] of Integer;
     B : Array [1..4] of Integer;

Begin
    A := B;

Won't work as loren-pechtel said here the problem is A and B for me are in different units. So, is there a way to define a type definition from a existing one in another class?

Was it helpful?

Solution

Define type in interface block of some unit and then include that unit via uses clause in other units where you need that type.

unit A;
interface
type
  TMyArray = array [1..4] of Integer;

...

When you need to use TMyArray in another unit:

unit B;
interface
uses A;

...
var x : TMyArray;

OTHER TIPS

Alternatively, define your type in the interface section of unit C and use this unit in both A and B.

Array types in Delphi are a bit odd. It looks like A and B are of exactly the same type, but Delphi doesn't consider that they are the same. "Array [1..4] of Integer" appears twice, so Delphi thinks there are two different types. That's just an oddity of Delphi. Most other languages, I think, wouldn't care. It's not a problem in practice; it's just a bit strange. Maybe there is a good reason for it. Who knows. The solution, as the others have said, is define your own type, which you can put in a unit that can be used by other units. I just mention this issue of array types because it may be confusing you.

Another approach, a bit old school but still works, is to use the ABSOLUTE keyword to force the memory of one to overlay another, and make the other type compatible. For example, in unit a lets say you have the following:

TYPE
  TArrayA = Array[1..4] of integer;

then in unit b, you have the following:

TYPE
  TArrayB = Array[1..4] of integer;  

For compatibility, you can do the following:

VAR
  InstanceA : TArrayA;
  InstanceB : TArrayB;
  InstanceBasA : TArrayA ABSOLUTE InstanceB;

What this does is create a variable "InstanceBasA" of type ArrayA which overlays the same memory space as the variable "InstanceB". This allows you to do the following command:

InstanceA := InstanceBasA;

One more method of moving data from variablea to variableb is to use the MOVE command. For example, to move from ArrayA to ArrayB you can do the following:

var
  ArrayA : array[1..4] of Integer;
  ArrayB : Array[1..4] of Integer;
begin
  FillChar(ArrayB[1],SizeOf(ArrayB),#0);
  ArrayA[1] := 1234;
  ArrayA[2] := 3456;
  ArrayA[3] := 7890;
  ArrayA[4] := 9876;

  // This is where the move from ArrayA to ArrayB happens.
  Move( ArrayA[1], ArrayB[1], SizeOf(ArrayA) );

  Assert( ArrayA[4] = ArrayB[4], 'ArrayA[4] <> ArrayB[4]');
end;

This works by the fact that the array is layed out in a linear fashion, so your copying the bytes starting at the first array position, for the length of the array.

You can force the compiler to assume they are of the same type by typecasting them:

type
  TIntArray = array[1..4] of integer;

begin
  Assert(SizeOf(ArrayA) = SizeOf(TIntArray));
  Assert(SizeOf(ArrayB) = SizeOf(TIntArray));
  TIntArray(ArrayA) := TIntArray(ArrayB);

But you should make sure that both actually are array[1..4] of otherwise you will overwrite some memory. That's why I added the two assertions.

Just use UnitA in UnitB after inteface and before the implementation ...!!!!

Never, never, NEVER use code like this:

// This is where the move from ArrayA to ArrayB happens.
Move( ArrayA[1], ArrayB[1], SizeOf(ArrayA) );

Where's the flaw? You're using the SOURCE size to get the number of bytes to move, not the DESTINATION size!!! If SizeOf(A) > SizeOf(B) you have a buffer overflow and you're overwriting memory. If you're luck you get an AV, if you're not you have an exploitable vulnerability. It's far better to always use the destination size, although this way you can end up reading memory you shouldn't if Size(B) > Size(A), maybe exposing unwanted data. Anyway, always check structure boundaries when moving data - some companies banned operations like this (i.e. memcpy() ) from their code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top