DLLs, PChar and string

hi all

i ahve written a function in a dll and it requires several string parameters.

i have read the help file and it says that ShareMem needs to be included if i am using strings. i want to avoid this. what is the common string type used? PChar?

i have tried this:

DLL routine:
------------
procedure one (s: PChar);
var
  str: string;
begin
  str := string (s);
  Showmessage(str);
end;

calling routine:
----------------

procedure Button1OnClick (Sender: TObject);
begin
  One (PChar(edtTest.Text));
end;


I managed to get garbage characters. obviously i am not doing it right. i am used to working with strings, so in the DLL, i want to convert PChar to string. also, how do i ensure that the string i have converted is valid? ie not garbage, regardless of of how the calling routine has defined it...

Regards
Keith
LVL 1
keithcslAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

LischkeCommented:
Hi Keith,

yes, using PChar is the way to go here. You should consider PChars as being pointers to a memory location nothing else, even if the were produced from Delphi strings. To convert them into strings you can use:

procedure one (s: PChar);
var
  str: string;
begin
  SetString(str, s, StrLen(s));
  Showmessage(str);
end;

Ciao, Mike
0
MadshiCommented:
Well, I really don't know why this:

var
  str: string;
begin
  str := string (s);
 
is not working! It should IMO... It does normally... Strange...

Your sources look alright to me...

Regards, Madshi.
0
keithcslAuthor Commented:
Hi Mike

I am still getting funny characters. It looks like the string received by the DLL routine is pointing to the wrong part of the memory.

My declarations:

DLL:
----
procedure One (pc: PChar); stdcall;

Calling App:
------------
procedure One (pc: PChar);  external 'Test.dll';

I call it using:

  One(PChar('aaa'));

I get something like %+p in the showmessage.

Keith
0
Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

keithcslAuthor Commented:
Sorry, note that I have changed (s: PChar) to (pc: PChar).
0
LischkeCommented:
Madshi, I never used this kind of type casting. Can this work (think of place for the reference counter and the memory size in normal strings)?

Keith, you haven't accidently forgotten to declare:

Calling App:
------------
procedure One (pc: PChar);  external 'Test.dll'; stdcall;

(Note: the calling convention!)?

Ciao, Mike
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
keithcslAuthor Commented:
Sorry, note that I have changed (s: PChar) to (pc: PChar).
0
LischkeCommented:
Keith, I just wrote a little test program which works fine:

DLL
-----------------------

library Test;

uses
  SysUtils, Dialogs,
  Classes;

{$R *.RES}

procedure One(pc: PChar); stdcall;

var
  S: String;

begin
  SetString(S, pc, StrLen(pc));
  ShowMessage(S);
end;

exports
  One;

begin
end.

-----------------------------------

Testprogram:

unit Unit1;

interface

uses Windows, SysUtils, Forms, Classes, StdCtrls, Controls,
     Buttons, Graphics, Dialogs, ComCtrls, Messages, ExtCtrls;


type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormKeyPress(Sender: TObject; var Key: Char);
    procedure Button1Click(Sender: TObject);
  private
  public
  end;

var
  Form1: TForm1;

procedure One(pc: PChar); stdcall;

implementation

{$R *.DFM}

procedure One(pc: PChar); external 'Test.dll'; stdcall;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if key = #27 then
  begin
    Key:=#0;
    Close;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  One('aaa');
end;

end.


Ciao, Mike
0
keithcslAuthor Commented:
ARGGH

i forgot to put the stdcall!

oh str := string(pc) works as well. now what r the dangers in doing this?

Keith

0
MadshiCommented:
Mike, I guess, the compiler simply replaces the "string()" type conversion with "SetString". I never used SetString. I'm always using the type conversion - and it works perfectly...   :-)

Regards, Madshi.
0
MadshiCommented:
Keith, no dangers, I think...   :-)
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.