Solved

Delphi DLL with exports and objects

Posted on 1999-01-24
14
575 Views
Last Modified: 2010-04-06
I am trying to use the NMHTTP component in a DLL and export a function which will manipulate the component. I am not trying to export the components methods, only a function I write which will use the component. I cannot seem to successfully get the component created without a form, and even then I still cannot get it to work. Can anyone provide some sample code for using a component in a DLL and exporting functions which will control that component? I already have created the DLL with no components in it and I can call and retrieve the return from my other language just fine...
0
Comment
Question by:dave5050
  • 7
  • 6
14 Comments
 
LVL 13

Accepted Solution

by:
Epsylon earned 1000 total points
ID: 1363113
I think you forgot to create the object in the dll initialisation code.
Something like NMHTTP.Create(owner) should be used.
Look at this:

------------------ Example -----------

library Test;

var
  SaveExit: Pointer;
  nm_http: NMHTTP;

procedure LibExit;
begin
  ...  // library exit code
  nm_http.free;
  ExitProc := SaveExit;  // restore exit procedure chain
end;

begin
  ...  // library initialization code
  SaveExit := ExitProc;  // save exit procedure chain
  ExitProc := @LibExit;  // install LibExit exit procedure
  nm_http := NMHTTP.Create(nil);
end.

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

Export your control functions as usual....


0
 

Author Comment

by:dave5050
ID: 1363114
Epsylon, Good answer but your sample does not compile. It barfs when declaring nm_http and such in the var section. For another 300-500 points can you provide a working sample also with a sample call to nm_http.get(url) and how to respond to events from the nm_http component?
0
 
LVL 7

Expert Comment

by:BlackMan
ID: 1363115
dave5050, you need to add the required units to a Uses statement to get the sample to compile...
0
 

Author Comment

by:dave5050
ID: 1363116
BlackMan, I did that and that resolved the problem, though I cannot reference the component anywhere...am I missing something with the scope?
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1363117
Sorry it's not NMHTTP but TNMHTTP.

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

library Project1;

uses
  SysUtils,
  nmhttp,
  Classes;

var
  SaveExit: Pointer;
  nm_http: TNMHTTP;

procedure LibExit;
begin
// library exit code
  nm_http.Free;
  ExitProc := SaveExit;  // restore exit procedure chain
end;

begin
// library initialization code
  SaveExit := ExitProc;  // save exit procedure chain
  ExitProc := @LibExit;  // install LibExit exit procedure
  nm_http := TNMHTTP.Create(nil);
end.

0
 

Author Comment

by:dave5050
ID: 1363118
Epsylon: You got the 500, but as I mentioned, for another 300-500 can you also provide a means for responding to this components events within the DLL? What you listed works well for init'ing the component and such, I can now call some methods of the component but in my other unit I have to redeclare the component again. Anyway, can you provide some info on responding to events? I don't know if I can keep this question open but still give you the 500...
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1363119
Here is a TNMHTTP.Get example which uses an OnConnect Event. You can try it with a clean form in a new/clean project. Then add a button, a checkbox, two memo's and a NMHTTP component to the form:

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

procedure TForm1.Button1Click(Sender: TObject);
begin
  NMHTTP1.OnConnect := NMHTTP1Connect; // Initialize the eventhandler
  NMHTTP1.InputFileMode := FALSE;
  NMHTTP1.OutputFileMode := FALSE;
  NMHTTP1.ReportLevel := 2; //Status_Basic - Deplhi 4 does not know 'Status_Basic' anymore I guess, maybe Delphi 3 does...
  If CheckBox1.Checked then
  Begin
    NMHTTP1.Proxy := 'wwwproxy.server.com';  // change this to your own needs
    NMHTTP1.ProxyPort := 8080;  // change this to your own needs
  End;
  With NMHTTP1.HeaderInfo do
  Begin
    Cookie := 'Hello world';
    LocalMailAddress := 'clinton@whitehouse.com'; // not nescessary
    LocalProgram := '';  // You can use this if you want
    Referer := '';  // You can use this if you want
    UserID := '';  // You can use this if you want
    Password := '';  // You can use this if you want
  End;
  NMHTTP1.Get('www.inprise.com');
  Memo1.Text := NMHTTP1.Body;
  Memo2.Text := NMHTTP1.Header;
  If NMHTTP1.CookieIn <> '' then
    ShowMessage('Cookie:'+#13#10+NMHTTP1.CookieIn);
end;

procedure TForm1.NMHTTP1Connect(Sender: TObject);
begin
  ShowMessage('YES I am connected!!!');
end;

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

Then add    

  procedure NMHTTP1Connect(Sender: TObject);

in the   TForm1 = class(TForm)   definition in the upper part of the source.
You can of course assign an eventhandler using the object inspector of delphi. You don't have to initialize the eventhandler in the Button1Click function then.

0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:dave5050
ID: 1363120
ARRRGH!!...;) Epsylon...I know how to do such using a form and application, what I am having problems with is doing it in a DLL.

Using your code in the init section of the DLL I get the component created just fine, in the uses clause I have also
"uses unit1 in unit1.pas" in which I have to redeclare  "nm_http: TNMHTTP" to be able to use it in that unit.

I export a function in the DLL called PostData index 1; and in the unit1.pas I have a function prototyped as "function PostData(var Type: Integer): LongBool; cdecl; export;" then in the function itself I do a nm_http.get(url) and then return a bool.

What I was asking regarding events, is how do I respond to nm_http events in the DLL?

procedure nm_http.OnPacketRecvd(Sender: TObject) does not work or trap the events...

what am I missing?

Thank you very much for the help you have been....want some contract work?...;)
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1363121
My previous comment was a response to your comment on Sunday, January 24 1999 - 06:15PM. You posted another comment on Monday, January 25 1999 - 03:08PM I had not seen at that time. So I just give a quick example that works.
I WILL help you further with but give my some time, then will work it all out. After all, we want the DLL to work!

On the OnPacketRecvd event: you have to assign a function to the OnPackedRecvd 'property' (OnPackedRecvd := SomeMethod). Events are method pointers. And since there is no form, there is no method. So it's a bit tricky.

It's late now (past midnight) so I will try to work it out tomorrow.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1363122
Hi Dave5050 or should I call you Dave. It works!

I created two Delphi projects: one for the DLL and one for testing the DLL. I will post the source code in the next comments. Use it as an example for your own code.


The 'DLLTester' app uses Form1 with:
- Button1
- Label1 with caption:='DLL timer active' and Visible:=false
- Label2
- Label3
- Edit1 with text:='http://www.inprise.com'
- Memo1

Click the button to active. Label1 should start blinking, Label2 should show the number of bytes received, Label3 should show 'Connected...' and Memo should contain the body of the requested url.



If you want to have the OnPacketRecvd event to call a handler INSIDE the DLL then remove the SetPacketRecvdEventHandler call from the DLL test app and add this to the DLL code:


type
  TDLLHandlerObject = class
    procedure mhoPacketRecvd(Sender: TObject);
  end;
  .....

var
  DLLHandler: TDLLHandlerObject;
  .....

procedure TDLLHandlerObject.mhoPacketRecvd(Sender: TObject);
Begin
  // your eventhandler code
end;


To assign the eventhandler put in the library initialization code after the creation of the nm_http object:

  DLLHandler := TDLLHandlerObject.Create;
  SetPacketRecvdEventHandler(DLLHandler.mhoPacketRecvd);

and in the library exit code:

  DLLHandler.Free;



well, I hope I have not forgotten anything.... good luck with it!

Let me know if it works.....
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1363123
Here is the DLL code

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

library DLLProject;

uses
  SysUtils,
  Classes,
  dialogs,
  extctrls,
  Psock,
  NMHTTP;

var
  SaveExit: Pointer;
  Timer: TTimer;
  nm_http: TNMHTTP;

procedure SetTimerEventHandler(eventhandler: TNotifyEvent);
begin
  Timer.OnTimer := eventhandler;
end;

procedure SetPacketRecvdEventHandler(eventhandler: TNotifyEvent);
begin
  nm_http.OnPacketRecvd := eventhandler;
end;

procedure SetConnectEventHandler(eventhandler: TNotifyEvent);
begin
  nm_http.OnConnect := eventhandler;
end;

function nmhttpBytesRecvd:Longint;
begin
  Result := nm_http.BytesRecvd;
end;

function nmhttpGet(url: String):String;
begin
  with nm_http do
  begin
    InputFileMode := False;
    OutputFileMode := False;
    ReportLevel := Status_Basic; // defined in Psock unit
//    Proxy := '192.168.0.1';
//    ProxyPort := 80;
    Get(url);
    Result := Body;
  end;
end;

procedure LibExit;
begin
// library exit code
  nm_http.Free;
  Timer.Free;
  ExitProc := SaveExit;  // restore exit procedure chain
end;

exports
  SetTimerEventHandler index 1 name 'SetTimerEventHandler',
  SetPacketRecvdEventHandler index 2 name 'SetPacketRecvdEventHandler',
  SetConnectEventHandler index 3 name 'SetConnectEventHandler',
  nmhttpGet index 4 name 'nmhttpGet',
  nmhttpBytesRecvd index 5 name 'nmhttpBytesRecvd';

begin
// library initialization code
  Timer := TTimer.Create(nil);
  Timer.Interval := 300;
  Timer.Enabled := true;
  nm_http := TNMHTTP.Create(nil);
  SaveExit := ExitProc;  // save exit procedure chain
  ExitProc := @LibExit;  // install LibExit exit procedure
end.

0
 
LVL 13

Expert Comment

by:Epsylon
ID: 1363124
Here is the test app code

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

unit DLLTester;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Memo1: TMemo;
    Label3: TLabel;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    procedure TimerCallback(Sender: TObject);
    procedure PacketRecvdCallback(Sender: TObject);
    procedure ConnectCallback(Sender: TObject);
    { Private declarations }
  public
    { Public declarations }
  end;
  procedure SetTimerEventHandler(eventhandler: TNotifyEvent); external 'DLLProject.dll';
  procedure SetPacketRecvdEventHandler(eventhandler: TNotifyEvent); external 'DLLProject.dll';
  procedure SetConnectEventHandler(eventhandler: TNotifyEvent); external 'DLLProject.dll';
  function nmhttpGet(url: String):String; external 'DLLProject.dll';
  function nmhttpBytesRecvd:Longint; external 'DLLProject.dll';

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.TimerCallback(Sender: TObject);
begin
  Label1.Visible := not Label1.Visible;
end;

procedure TForm1.PacketRecvdCallback(Sender: TObject);
begin
  Label2.Caption := IntToStr(nmhttpBytesRecvd);
end;

procedure TForm1.ConnectCallback(Sender: TObject);
begin
  Label3.Caption := 'Connected...';
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetTimerEventHandler(TimerCallback);
  SetPacketRecvdEventHandler(PacketRecvdCallback);
  SetConnectEventHandler(ConnectCallback);
  Memo1.Text := nmhttpGet(Edit1.Text);
end;

end.

0
 

Author Comment

by:dave5050
ID: 1363125
Adjusted points to 1000
0
 

Author Comment

by:dave5050
ID: 1363126
Epsylon, EXCELLANT. That is what I was looking for. I have not tested your code entirely but what I see is exactly what I was needing. I just need to apply it to my application. Here is 1000 points as promised and I appreciate your help. If you are interested in some contract work using Delphi 16/32 contact me. -Dave
dave@calinet.com
California Internet Connection
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Internet Explorer View Settings Question 15 99
FMX enumerated colours 2 72
oracle global variables 4 52
Base1 Encode/Decode 3 35
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.

762 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

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now