Recent

Author Topic: PAnsiChar to String  (Read 45974 times)

EMTR

  • New Member
  • *
  • Posts: 20
PAnsiChar to String
« on: November 06, 2009, 01:57:12 pm »
I'm having a problem converting a PAnsiChar to a string...

I have an exe and a dll hence the need to use a PAnsiCHar at all...

My dll function is...

function ABC(const PA : PAnsiChar; out DEF : Integer) : Boolean; stdcall;
begin
  // I need to convert from a PAnsiChar to a string
  // String(PA) doesnt work
  // StrPas(PA) doesnt work
  doSomethingWithAString(PA);
end;

What conversion do I need here?!?!?

Vincent Snijders

  • Administrator
  • Hero Member
  • *
  • Posts: 2661
    • My Lazarus wiki user page
Re: PAnsiChar to String
« Reply #1 on: November 06, 2009, 02:07:56 pm »
I would try:
Code: [Select]
{$H+}
function ABC(const PA : PAnsiChar; out DEF : Integer) : Boolean; stdcall;
var
  S: String;
begin
  // I need to convert from a PAnsiChar to a string
  S:= PA;
  doSomethingWithAString(S);
end;

jetchengchu

  • Guest
Re: PAnsiChar to String
« Reply #2 on: November 06, 2009, 02:11:53 pm »
If you use {$H+} (i.e. string as AnsiString), I guess no explicit conversion is needed.

Code: [Select]
{$H+}

procedure Test(D: PAnsiChar);
var
  S: string;
begin
  S := D;
  Writeln(Integer(D));  { Prints the value of D. }
  Writeln(Integer(S));  { This differs from that of D. }
  Writeln(S);
end;


var
  S: array [0..3] of AnsiChar;

begin
  S := 'Test';
  Test(@S);
end.

This compiles and works correctly.

Vincent Snijders

  • Administrator
  • Hero Member
  • *
  • Posts: 2661
    • My Lazarus wiki user page
Re: PAnsiChar to String
« Reply #3 on: November 06, 2009, 02:14:52 pm »
Jetcheng Chu, EMTR has a pchar value and wants to call a procedure with a string  parameter:
procedure Test(s: string);

jetchengchu

  • Guest
Re: PAnsiChar to String
« Reply #4 on: November 06, 2009, 02:22:27 pm »
Well in that case, simply do something like Test(S) where S is a PAnsiChar (i.e. no explicit conversion needed, either).

EMTR

  • New Member
  • *
  • Posts: 20
Re: PAnsiChar to String
« Reply #5 on: November 06, 2009, 02:59:43 pm »
Sorry, Maybe I wasn't clear enough... my actual code is this...

Code: [Select]
// Std call - this is the function exported from the dll...
function GetDetails(const Name : PAnsiChar; out val : Longword) : Boolean; stdcall;
var
  data : TCompanyData;
begin
  data := TCompanyData.Instance;
  Result := data.get(Name, val);
end;


// Within the dll I have some objects, common code, etc. I'm calling a function to get me some data for a given name
Code: [Select]
function TCompanyData.Get(const Name: string; out CRC : Longword) : Boolean;
begin
  // This bit should work - I get into and out of this function but by the time I get here Name is incorrect...
end;

I've written the calling code in Delphi 2009. The dll then needs to convert back from a PAnsiChar to an AnsiString (just a string) to go away and get me some information.

// Note: Lazarus wont let me debug the DLL so I'm left with dumping info to a file.
// Nothing I've tried works... (judging from the info in the file I dump out)
// For Example suppose "Name" is "Charlie"
Code: [Select]
function GetDetails(const Name : PAnsiChar; out val : Longword) : Boolean; stdcall;
var
  data : TCompanyData;
  list : TStringList;
  temp : string;
begin
  temp := Name;
  list := TStringList.Create;
  list.Add(Name);                  // produces 'C'
  list.Add(StrPas(Name));          // produces 'C'
  list.Add(temp);                  // produces 'C'  // In Delphi 2009 I believe this would be "Charlie"
list.SaveToFile('C:\test.txt');
  data := TCompanyData.Instance;
  Result := data.get(Name, val);
  
end;


I've included the directive {$H+}. The result I'm looking for is temp ( in my second example code ) to be 'Charlie' - Any thoughts?! I've tried all manner of Copy, StrPCopy, etc... Can't seem to get Free Pascal / Lazarus to do this.
« Last Edit: November 06, 2009, 03:07:00 pm by EMTR »

jetchengchu

  • Guest
Re: PAnsiChar to String
« Reply #6 on: November 06, 2009, 03:11:47 pm »
How did you invoke GetDetails()?

EMTR

  • New Member
  • *
  • Posts: 20
Re: PAnsiChar to String
« Reply #7 on: November 06, 2009, 03:20:00 pm »
Invoked from a calling program written in delphi 2009.

The call to the function is literally just Data(PAnsiChar(string)) - note: string at this time is correct....

// Note this works in practice...
Code: [Select]
function TCompanyForm.DllData(const Name : string): Boolean;
const
  GET_DATA = 'GetDetails';
var
  dllHandle : THandle;
  val : longword;
  Data : function GetDetails(const Name : PAnsiChar; out val : Longword) : Boolean; stdcall;
begin
  Data := GetProcAddress(dllHandle, GETDATA);
  Data(PAnsiChar(Name), val);
  // do some checking on val etc...
end;

I get into the dll - but I need to write the dll using Lazarus, otherwise I'm sure I wouldn't even have this issue...

The conversion of PAnsiChar to String in the dll is the problem, rather than the calling code but I can't figure out a way to resolve?
« Last Edit: November 06, 2009, 03:22:38 pm by EMTR »

EMTR

  • New Member
  • *
  • Posts: 20
Re: PAnsiChar to String
« Reply #8 on: November 06, 2009, 03:35:16 pm »
Anyway to clarify I'm looking for a way to simply convert PAnsiChar to String. I'm sure its trivial. I just cant see what I've missed or where I'm going wrong...

jetchengchu

  • Guest
Re: PAnsiChar to String
« Reply #9 on: November 06, 2009, 04:02:28 pm »
In your Delphi code, try using AnsiString instead of string.

EMTR

  • New Member
  • *
  • Posts: 20
Re: PAnsiChar to String
« Reply #10 on: November 06, 2009, 04:09:46 pm »
:( no reply?

Sorry Im really impatient!

to update you...

Code: [Select]
function GetDetails(const Name : PAnsiChar; out val : Longword) : Boolean; stdcall;
var
  data : TCompanyData;
  list : TStringList;
  temp : AnsiString;
begin
  temp := Name;
  list := TStringList.Create;
  list.Add(Name);                  // produces 'C'
  list.add(Name[1]);');           // 'C'
  list.add(Name[2]);');           // ' '
  list.add(Name[3]);');           // 'h'
  list.add(Name[4]);');           // ' '
  list.Add(StrPas(Name));          // produces 'C'
  list.Add(temp);                  // produces 'C'  // In Delphi 2009 I believe this would be "Charlie"
  list.SaveToFile('C:\test.txt');
  data := TCompanyData.Instance;
  Result := data.get(Name, val);
 
end;


Switching string for AnsiString in the dll code (see above) makes no difference...

Using PAnsiChar[index] as an array gives me a character by character output of "Name" but its not what I want - I'm looking for the whole string.

I can write a function to builda string but how do I know how long PAnsiCHar (Name) is?!? Any thoughts welcome - dont just read make a comment!!! lol

leocda

  • Jr. Member
  • **
  • Posts: 60
  • Computer Graphics researcher
    • Picture to People
Re: PAnsiChar to String
« Reply #11 on: November 06, 2009, 04:13:55 pm »
Quote
I can write a function to builda string but how do I know how long PAnsiCHar (Name) is?!? Any thoughts welcome - dont just read make a comment!!! lol

A PAnsiChar is a pointer to a null-terminated string of 8-bit characters.

It's just like we make in C. We loop over the char (byte) elements until we find an element with a value of 0.
« Last Edit: November 06, 2009, 04:22:36 pm by leocda »

EMTR

  • New Member
  • *
  • Posts: 20
Re: PAnsiChar to String
« Reply #12 on: November 06, 2009, 04:16:52 pm »
OK! It works!

Changed the calling code to ansistring as suggested!

You'd have thought Delphi would treat string and ansistring the same in the following line in my CALLING app...
Code: [Select]
Data(PAnsiChar(Name), val);

jetchengchu

  • Guest
Re: PAnsiChar to String
« Reply #13 on: November 06, 2009, 04:21:46 pm »
You saw only a single letter because of the format of UnicodeString, which is the default string format in Delphi since Delphi 2009.

TurboRascal

  • Hero Member
  • *****
  • Posts: 672
  • "Good sysadmin. Bad programmer."™
Re: PAnsiChar to String
« Reply #14 on: November 22, 2009, 04:17:00 pm »
Yes, that's an usual porting problem since D2009.
In D2009 and newer, String defaults to UnicodeString, while all earlier versions (and Lazarus) default String to AnsiString.

The solution is to always explicitly declare AnsiString or UnicodeString for code that should be interchangeable between those versions, and avoid declaring variables as just String. Same goes for PChar vs. PAnsiChar etc.
Regards, ArNy the Turbo Rascal
-
"The secret is to give them what they need, not what they want." - Scotty, STTNG:Relics

 

TinyPortal © 2005-2018