We help IT Professionals succeed at work.

dll's

classic_gaming
on
hi,

i'm wondering if i can do this here goes.

i have a dll and i want my program to send it a string so it can return a certain number depending on the first letter of the string. a bit like creating a keycode for a user.

this is the dll code:

library testdll;

uses SysUtils, Classes, Dialogs;

{$R *.res}

procedure DllMessage(Sender: String); export;
var
in: integer;
begin
randomize;
in := random(9999);
ShowMessage('DLL Test #'+in);
end;

exports DllMessage;

end.

how can i make a programs that sends a string, so the dll can read and send back a number.

i hope anyone can help.

cheers
classic_gaming

Comment
Watch Question

Commented:
In a the external app unit,

//Define the global method(s)...
Procedure DllMessage(Sender:String);StdCall;
//...

Implements
//Then implement the defined method(s)
Procedure DllMessage; External 'TestDll';

You can now call your DllMessage, You can always look to the Windows.pas for examples on how to import methods from .dlls.
Good Luck,
RH.

Author

Commented:
hi,

is this right?

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    Procedure DllMessage(Sender:String);
  public
    { Public declarations }

  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure DllMessage; external 'testdll.dll'


procedure TForm1.Button1Click(Sender: TObject);
begin
dllmessage;
end;

end.

but when i compile i get the error message:
not enought actual parameters on the line "dllmessage;"

can anyone help?

cheers
classic_gaming

Commented:
Close,
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Button1: TButton;
   Edit1: TEdit;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

//Should be Global in Unit
Procedure DllMessage(Sender:String);StdCall;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure DllMessage; external 'testdll.dll';


procedure TForm1.Button1Click(Sender: TObject);
begin
//Needs a Value
dllmessage('a Value');
end;

end.

One other thing testdll.dll must be in the same folder as the exe using it.

RH.

Author

Commented:
hi,

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

Procedure DllMessage(Sender:String);StdCall;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure DllMessage; external 'testdll.dll';


procedure TForm1.Button1Click(Sender: TObject);
begin
dllmessage('a');
end;

end.

that works but returns a error any reason why it does that?
(the points are yours) :-)

cheers
classic_gaming

Commented:
What is the Error? and where does it happen?
RH.

Author

Commented:
when you click ok on the showmessage i'll post the error when i load the program...

"access violation at address 0044DBCB in module 'Project1.exe'. write of address 0042638c.

know what this is?

cheers
classic_gaming

Author

Commented:
the dll code is:

library testdll;

uses SysUtils, Classes, Dialogs;

{$R *.res}

procedure DllMessage(Sender: String); export;
var
s:string;
begin
if pos('a',s) <>1 then
begin
showmessage('Worked');
end else;
ShowMessage('DLL Test');
end;

exports DllMessage;

end.

is that right or something missing?

cheers
classic_gaming
Commented:
Got it,
You didn't compiled the dll export method using StdCall,
so remove StdCall from the line in the calling unit..
So Replace This..
Procedure DllMessage(Sender:String);StdCall;
With This..
Procedure DllMessage(Sender:String);

-Or-

Change the Dll by replacing this..
procedure DllMessage(Sender: String); export;
with this
procedure DllMessage(Sender: String); StdCall;

Either one, I would change the Dll to StdCall, that will allow easy access from multiple languages.

Good Luck,
RH.

Commented:
RH is right, the function must be defined TOTALLY identical in both your dll and in your application. But that's only the first half of the problem. The second half is that when using string parameters in dlls you need to add ShareMem to the uses clause of both your dll and your application project file (*.dpr) - and at the first location!!

program yourApplication;

uses
  ShareMem,  // must be first
  ...;

begin
  Application.Initialze;
  Application.CreateForm(...);
  Application.Run;
end.

library yourDll;

uses
  ShareMem,  // must be first
  ...;

begin
  ...
end.

Regards, Madshi.
You should not use strings in a DLL.
Strings need ShareMem unit in both program and DLL.
Also the DLL is not compatible with other programs not written in Delphi.
Better use the classic C approach here.

function DLLMessage(Buffer: PChar; Size: Cardinal): Cardinal; stdcall;

call it with

var
  Buffer: array [0..255] of Char;
  RetLen: Cardinal;
begin
  RetLen := DLLMessage(Buffer, SizeOf(Buffer));

You should also always use stdcall for all your DLL fucntions you ever write. The default calling convention register is also incompatible with other programming languages.

Commented:
If I understand correctly, the function will not modify the input string. Therefore I would make it simpler:

function MyDLLMessage(Msg: PChar): Cardinal; stdcall;

and document that a null-terminated string is expected.

Author

Commented:
hmm for some strange reason i couldnt access ee for the past few days since my last post. when i made my 2nd to last post i said RHuebner would get the points. so here you are. :)

thanks for all the help everyone
classic_gaming

Explore More ContentExplore courses, solutions, and other research materials related to this topic.