Array of Byte to PChar

GNiessen
GNiessen used Ask the Experts™
on
I am converting a DLL to XE from D7 and need to convert an array of Byte that is passed in to a PChar that can be passed to a StrMove.

I could write my own ByteMove, but am needing a similar conversion in other spots that are more complicated to explain.  

 
procedure Transpose(var Data, OrderData: array of Byte);
var
  TmpData: array[0..63] of Byte;
  i : Byte;
begin
  StrMove(@TmpData, @Data, SizeOf(Data));
  for i := 0 to High(OrderData) do
    Data[i] := TmpData[OrderData[i]];
end;

Open in new window


With D7 this worked.  But with the new PWideChar support in D2009+ it will not.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Geert GOracle dba
Top Expert 2009

Commented:
the clue is what you are passing to this procedure
and what are you trying to accomplish ?

the context of what you are doing is odd for unicode strings

have you checked the functions StringOf and BytesOf ?

Commented:
in <=D2007 PChar = PAnsiChar, Char = AnsiChar
in D2009+ PChar = PWideChar, Char = WideChar

SizeOf(PAnsiChar) = 1Byte
SizeOf(PWideChar) = 2Byte


try to run this code in different versions of delphi
  ShowMessage(Format('Size of "AnsiChar" %d, Size of "WideChar" %d, Size of "Char" %d', [SizeOf(AnsiChar), SizeOf(WideChar), SizeOf(Char)]));

Open in new window

Commented:
I wrote wrong
SizeOf(PAnsiChar) = 1Byte
SizeOf(PWideChar) = 2Byte
must be
SizeOf(AnsiChar) = 1Byte
SizeOf(WideChar) = 2Byte
HTML5 and CSS3 Fundamentals

Build a website from the ground up by first learning the fundamentals of HTML5 and CSS3, the two popular programming languages used to present content online. HTML deals with fonts, colors, graphics, and hyperlinks, while CSS describes how HTML elements are to be displayed.

Author

Commented:
In this case I have a fixed Byte Array of 64 characters getting passed in from another system.  There is some encryption being done that make accessing them as bytes more efficient then as an array of characters,  This is legacy code, so it is all AnsiChar.    I am not looking to make it Unicode enabled at this time.  
I guess you only need to get rid of the string based approach, and handle data simply as bytes instead.

procedure Transpose(var Data, OrderData: array of Byte);
var
  TmpData: array[0..63] of Byte;
  i : Byte;
begin
  Move(Data, TmpData, SizeOf(Data));
  for i := 0 to High(OrderData) do
    Data[i] := TmpData[OrderData[i]];
end;

Open in new window


It may worth thinking it over to pass PByte pointers to a function that expected PAnsiChar parameters, since it may lead to maintainability problems. I mean, finding a function with another parameter type is a good trail, even to another possible solution using the CopyMemory API as well.
Hello,

I guess you only need to get rid of the otherwise suspicious parameter passing - I mean, the StrMove expects PAnsiChars (in D7), so it should not deal with PByte pointers. You could move the data in a loop yourself byte by byte, or use one of the handful of functions like CopyMemory, MoveMemory, Move, etc..
As for me, I would prefer using Move as it seems to be the native solution:

procedure Transpose(var Data, OrderData: array of Byte);
var
  TmpData: array[0..63] of Byte;
  i : Byte;
begin
  Move(Data, TmpData, SizeOf(Data));
  for i := 0 to High(OrderData) do
    Data[i] := TmpData[OrderData[i]];
end;

Open in new window

" I mean, the StrMove expects PAnsiChars (in D7), so it should not deal with PByte pointers. "

Well, they are technically both pointers, hence why it works fine.
Well, I do not know if the author's concern ("But with the new PWideChar support in D2009+ it will not.") is realistic, since I have no D 2009+ on hand.

On the other hand, I see the online XE documentation showing two overloads for StrMove - there is one dealing with PAnsiChars and one with PWideChars.

Even if the code works fine - of which I am unsure - I would not dare to state it is not ambiguous for the compiler to determine which overload matches such a situation (pointer, pointer, integer).

Furthermore, for testing, I reproduced this with D7, so I received an "Ambiguous overloaded call to ..." error. Explicitly using a PAnsiChar typecast will most likely remedy the situation among the other solutions outlined above.

Like I expect

procedure Transpose(var Data, OrderData: array of Byte);
var
  TmpData: array[0..63] of Byte;
  i : Byte;
begin
  StrMove(PAnsiChar(@TmpData), PAnsiChar(@Data), SizeOf(Data));
  for i := 0 to High(OrderData) do
    Data[i] := TmpData[OrderData[i]];
end;

Open in new window


to be a syntactically correct, more explicit and therefore descriptive code piece.

Author

Commented:
While I agree with your comments on the ByteArray, sometimes there are reasons to not change things any more then required to make it work again.  So I will go with the StrMove and PAnsiChar.  Which was what I did and tested before, but was not sure it was the best or definitive solution.  And this might not have been the best example of what I have in other areas, but seems to have worked.  

Thanks

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial