tags:

views:

95

answers:

2

Question closed (answer accepted) replaced by http://stackoverflow.com/questions/3157732/delphi-7-access-violation-tbytedynarray-problem)


I have the following delcartion given to me

MyPhoto = class(TRemotable)
private
  FhasPhoto: Boolean;
  FphotoData: TByteDynArray;
published
  property hasPhoto: Boolean read FhasPhoto write FhasPhoto;
  property photoData: TByteDynArray read FphotoData write FphotoData;
end;

and I want to

var photo : MyPhoto;
photo := MyPhoto.Create();
SetLength(photo.photoData, 4);

but I get

[Error] mainForm.pas(340): Constant object cannot be passed as var parameter

1) How do I code it correctly, given that I can't change the definition of the class Photo?
2) can I effectively 'cast' any structure to a TByteDynArray just by assigning it?

(as you might have guessed, I'm a BCB guy trying to get into Ddlphi :-)


p.s I will settle for being able to assign each byte of the photo data individually...

+2  A: 

This is a flaw in Delphi's implementation of properties. Even if the property can be read and written to, even if both the read and the write point to the same field in the underlying object, you can't pass a property to a var parameter, such as to SetLength. There's no good reason for this, but that's the way it works, for the time being at least.

There's a fairly simple workaround for this issue, though. You need a method on the object that takes an integer and will set the length of FPhotoData internally.

Mason Wheeler
do you have any sample code for this workaround? Sorry, but I'm not really a Delphi guy ..
Mawg
I wouldn't call it a flaw. It is correct. Ty bypass it, declare a local variable: var x: TByteDynArray; begin x := photo.photoData; SetLength(x, ...); photo.photoData := x; end.But I would suggest adding a method "SetLength" to your MyPhoto class. Even this is not correct, you should abstract things even further.
alex
@Mason: this is correct: you cannot pass properties by reference (`var` or `out`). The reason is that properties - though sometimes backed by fields - are not fields. Delphi is not the only language disallowing to use properties as fields and pass them as reference parameters; C# does not allow it (http://stackoverflow.com/questions/529782/c-property-and-ref-parameter-why-no-sugar); Java passes everything by value anyway (http://www.yoda.arachsys.com/java/passing.html). I think C++ has the same behaviour as Delphi, but could not find an on-line reference about it.
Jeroen Pluimers
Alex (+1) your "kludge" worked. Thanks! If you will repost it as an answer then I will award you the answer.
Mawg
Alex, it compiled, but crashes on running. I will be posting a new question ....
Mawg
@Alex, @Jeroen: Of course they're not fields, but that's not the point. The point is that syntactically, they look exactly like fields to the user. Whether or not it's backed by a field is irrelevant. That's the whole point of the abstraction. But as soon as you try to pass a property--which otherwise looks exactly like a field--to a var parameter, the abstraction leaks. There's no good reason why you should ever be unable to pass a read/write property to a var parameter. The compiler should be able to extract the value to an implicit local variable, pass it, then send the result back.
Mason Wheeler
+1  A: 

Hi,

Here is a way :

MyPhoto = class(TRemotable)
  ...
public
  procedure SetSize( aSize : Integer );
end;

procedure MyPhoto.SetSize( aSize : Integer );
begin
  SetLength( FphotoData, aSize );
end; 


var photo : MyPhoto;
photo := MyPhoto.Create();
MyPhoto.SetSize(4);
LeGEC