![]() |
Componets in a dll
The following code is an attempt to put the Delphi7 demo application Delphi7/demos/Internet/netchat/netchat.dpr
into a dll I have used the dll wizard to set up the library code and then added a data unit to it. The data unit includes the TTcpServer and TTcpClient components from the Internet tab. any attempt to access the Client or Server componets via the dll just causes a hang. I also tried it with fastmem4 removed and tried starting a timer on the datamodule all with the same result. As you can see I have attempted to include fastmm4 (correctly?) and the string list which is meant to replace the memo in the demo seems to work OK (i.e I can read and write to it via the dll). CODE library Ethernet; { To avoid using sharemempass string information using PChar or ShortString parameters. } uses FastMM4 in 'FastMM4.pas', SysUtils, Classes, dataUnit in 'dataUnit.pas' {DataModule1: TDataModule}; {$R *.res} function Initalise: integer; stdcall; begin result := 0; MemRecv := TStringList.Create; // create a string list to hold recived messages memrecv.Add('Test line'); end; function StopAll: integer; stdcall; begin result := 0; try Freeandnil(Memrecv); Datamodule1.Server.Active := false; datamodule1.Client.Active := false; except result := 1; end; end; function ActivateServer(LocalP: shortstring; remoteH: shortstring; RemoteP: shortstring): integer; stdcall; begin result := 0; with DataModule1 do try // any one of these calls cause the app to hang!! Client.RemoteHost := RemoteH; Client.RemotePort := RemoteP; Server.LocalPort := LocalP; Server.Active := True; except result := 1; end; end; // read the first line out of the stringlist and delete it!! // this works as expeceted. function ReadLine: shortstring; stdcall; begin if MemRecv.Count > 0 then begin result := MemRecv.Strings[0]; Memrecv.Delete(0); end else result := 'NO DATA'; end; This is the data unit code (slightly) amended from the demo code. CODE unit dataUnit; interface uses fastmm4, SysUtils, Sockets, ExtCtrls, Classes; type TDataModule1 = class(TDataModule) Server: TTcpServer; Client: TTcpClient; procedure ServerAccept(Sender: TObject; ClientSocket: TCustomIpClient); private { Private declarations } public { Public declarations } end; TClientDataThread = class(TThread) private public ListBuffer :TStringList; TargetList :TStrings; procedure synchAddDataToControl; constructor Create(CreateSuspended: Boolean); procedure Execute; override; procedure Terminate; end; var DataModule1: TDataModule1; Memrecv: Tstringlist; implementation {$R *.dfm} //------------- TClientDataThread impl ----------------------------------------- constructor TClientDataThread.Create(CreateSuspended: Boolean); begin inherited Create(CreateSuspended); FreeOnTerminate := true; ListBuffer := TStringList.Create; end; procedure TClientDataThread.Terminate; begin ListBuffer.Free; inherited; end; procedure TClientDataThread.Execute; begin Synchronize(synchAddDataToControl); end; procedure TClientDataThread.synchAddDataToControl; begin TargetList.AddStrings(ListBuffer); end; //------------- end TClientDataThread impl ------------------------------------- procedure TDataModule1.ServerAccept(Sender: TObject; ClientSocket: TCustomIpClient); var s: string; DataThread: TClientDataThread; begin // create thread DataThread:= TClientDataThread.Create(true); // set the TagetList to the output string list. DataThread.TargetList := memRecv; // Load the Threads ListBuffer DataThread.ListBuffer.Add('*** Connection Accepted ***'); DataThread.ListBuffer.Add('Remote Host: ' + ClientSocket.LookupHostName(ClientSocket.RemoteHost) + ' (' + ClientSocket.RemoteHost + ')'); DataThread.ListBuffer.Add('===== Begin message ====='); s := ClientSocket.Receiveln; while s <> '' do begin DataThread.ListBuffer.Add(s); s := ClientSocket.Receiveln; end; DataThread.ListBuffer.Add('===== End of message ====='); // Call Resume which will execute and synch the // ListBuffer with the TargetList DataThread.Resume; end; end. |
As a new member, it would be polite and sociable for you to read the rules/FAQ, particularly with regard to the use of code tags.
|
Sorry about that: The original location of this post did indeed have [code[/code] tags, but they didnt come across in the paste.
Shortage of time to completion of this project meant I needed help with this as quickly as possible. Hence the lack of time to Read the [rules] as I should and now have. Once again sorry. BTW the code doesnt explicitly create the datamodule in the DLL which has now been sorted out but there are still problems with the operation Steve |
Could you please repost the code with the [code] tags? It's very difficult to read without proper formatting.
|
Here is the code in tags,
Please notice the ammended part (lack of implict creation of the data module)which was causing the hang. However there are still problems in that although my fire wall detectes activity, the dll still dosent seem to be able to transmitt or recieve messages. :
library Ethernet;This is the data unit code (slightly) amended from the demo code. :
unit dataUnit; |
I cant see any Client or Server var declarations?! Well even if they are there, then you make it all wrong. You need to supply your dll host app with pointer to class instance variable. for example
some code in DLL: :
|
Thanks for your reply, not sure I fully understand, heres are some of the calling functions maybe you can put it more in context?
:
procedure TForm1.Button1Click(Sender: TObject); |
:
procedure TForm1.Button1Click(Sender: TObject);firstly, i dont see the reason why you use try except block?:confused: you have no crash unsafe calls there so you can easly remove it. secondly, could you supply more info what components you want to implement in your DLL?:) and what is MessageBox in your case? Is it the component created by DLL? |
Thanks for the Reply Jimmy
Yes not done (much/anything) with DLL's untill now so I wasnt sure if errors would propergate out of the DLL or how they should be handled! We were going to put the Client server demo from the Delphi7 Intenet tab into the DLL , but now this dosnt seems to be the correct thing to do. So what I now propose to use is the Indy IDTCPServer component, and the functionality will be based around the Demo code for this component. in Indy/demos/IIdTCPDemo/Server. We are starting to make some progress getting the application version of this talk to to our hardware (PIC Micro) server. But our costomer wants a DLL so he can do something with VB. Steve |
One more thing to know...
OK, Steve. Also I'd like to aware you of problem of calling conventions missmatch, that is, you need to specify the StdCall convention to make sure that your exported function will work in VB. By default, Delphi uses Register calling convention, so the parameters are passed from left to right, and if possible, through CPU registers instead of creating new stack frame. But compilers (intepreters) from Microsoft and many other developers use StdCall convention by default (as all functions of WinAPI). Under StdCall calling convention parameters are passed from right to left and always on the stack.
;) |
| All times are GMT -5. The time now is 12:27 PM. |
Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC