Solved

Array of Byte to PChar

Posted on 2011-09-02
9
2,485 Views
Last Modified: 2012-05-12
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.
0
Comment
Question by:GNiessen
  • 3
  • 2
  • 2
  • +2
9 Comments
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 36475089
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 ?
0
 
LVL 3

Expert Comment

by:VahaC
ID: 36475195
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

0
 
LVL 3

Expert Comment

by:VahaC
ID: 36475201
I wrote wrong
SizeOf(PAnsiChar) = 1Byte
SizeOf(PWideChar) = 2Byte
must be
SizeOf(AnsiChar) = 1Byte
SizeOf(WideChar) = 2Byte
0
Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

Author Comment

by:GNiessen
ID: 36475262
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.  
0
 
LVL 3

Expert Comment

by:brezniczky
ID: 36476506
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.
0
 
LVL 3

Expert Comment

by:brezniczky
ID: 36476524
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

0
 
LVL 13

Expert Comment

by:ThievingSix
ID: 36478451
" 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.
0
 
LVL 3

Accepted Solution

by:
brezniczky earned 250 total points
ID: 36478638
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.
0
 

Author Closing Comment

by:GNiessen
ID: 36489873
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
0

Featured Post

Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…

821 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question