tags:

views:

132

answers:

5

Hi, ive previously asked another questions about building my dll, but it seams like its heading in the wrong direction :) So I have reformulated and explained more her.

So what im trying to build is a dll that will work as an interface between my delphi program and some one else's C program.

What this dll must do is recive a String from the C program then send it to the delphi program where it will be combined with some data and stored, under the current user of my program.

How can i call a method in my Delphi program(running program) to store the message from the dll ?

Im using Delphi 5. This is what ive got so far:

DLL:

//Parent application: MyDelphiApp   
library MyDllLink; 

uses
  ShareMem,
  SysUtils,
  Classes,
  Dialogs,
  Main;// Main is a form from my delphi app. This is not allowed/recomended ?

{$R *.RES}


procedure Transfer(sMessage: PChar); stdcall;
begin
    try
        //If including Main in the uses clause, then this will also be wrong:
        MainForm.StoreDllMessage(sMessage);
    except
        showmessage('Error');
    end;    
end;

exports
Transfer;

end.

Delphi app:

procedure TMainForm.StoreDllMessage(sMessage: String);
begin
    //StoreMessage just stores it in a DB
    StoreMessage(sMessage +' '+sCurrentUserName);
end;
A: 

The DLL must callback to the Delphi program. When the Delphi program starts up, it'll register a callback function. Then the DLL knows what to call when it is invoked by the C program.

Example: http://delphi.about.com/od/windowsshellapi/a/callback_delphi.htm This example uses a callback to allow the windows API to call back into your delphi app. Same idea here, but instead of the Windows API, you're going to be called by your own DLL.

Chris Thornton
Never used call back before, will look into it. Feel free to link to some tutorials if you got any :)
Roise
@Shunty is right - the memory model won't work. i.e. the C program would be calling a different instance of the DLL than the one attached to your app. Best to have the DLL send you a WM message, write to a simple database, use mailslots, etc..
Chris Thornton
Right, each program will have a different Memory space allocated for the dll, callback registered from Delphi will not will not fire when the c program push data...
jachguate
+4  A: 

I may be understanding this wrong but it seems like you want the same copy of the DLL to be loaded by both the C program and the Delphi program at the same time. You can't do that and can only really achieve it using a whole lot of work involving inter process communication. The applications will have separate process space and memory.

I would suggest a slightly different approach. In the DLL have a function called SendStringFromCApp and a function called GetStringIntoDelphiApp (or something suitable).

The C program will load a copy of the DLL as normal and call the SendStringFromCApp function. This function will store the passed in data in some common intermediate format (such as a simple database). It will treat the storage as a kind of queue and simply add data to this queue. A database is the most obvious choice but it could be as simple as a common directory and the data is stored as small text files with an increasing integer as the file name.

The Delphi program will load its own copy of the DLL and will call GetStringIntoDelphiApp which will read the first item from the queue/internal storage and process it as required and delete it from the store. Then it will read the next etc etc.

The benefit of this is that both the C and Delphi apps can run independently. Only the DLL needs a common config and the C program can continue to work even if the Delphi app isn't running and vice versa.

It's basically a producer-consumer queueing system for separate processes.

Like I said, I may have misunderstood the requirements!

shunty
It needs to happen "instantly" so this approach would not work for me at all. Where in the DB the information that is sent in by the C app needs to be stored, changes often so this kind of delay will cause the data to be stored in the wrong places.
Roise
Fair enough. In which case I would take a look at using something like the Windows WM_COPYDATA message from your C app (or via the DLL) posting to your Delphi app. In that case only the C app will need access to the DLL. Trying to share a DLL between processes won't work.
shunty
+1  A: 

Try implementing an IPC (InterProcess Communication). You will have 3 separated processes.

  1. The Delphi exe
  2. Ths C program
  3. A non windowed process (com service, exe, ...)

Use the non windowed as the server, the other 2 are clients. See this for IPC in Delphi, and this for IPC in C. There is a lot of ways to do IPC. If you look for IPC in your favorite search engine I'm pretty sure that you will find a common way to do IPC for C and Delphi because it's just some win32 api ballet.

loursonwinny
Since im not going to program the C part it seams over complicated to use this approach.
Roise
and what about a dll called by a C program, receiving the string. And that dll alone communicate through IPC with the Delphi program. between two delphi processes, it is more than easy to do IPC with those components 'http://home.roadrunner.com/~rllibby/source.html', go there and look for 'pipes.zip'. You'll have a TPipeServer and a TPipeClient
loursonwinny
+1  A: 

As loursonwinny says, IPC is the way to go.
You should understand that every DLL is loaded within the address space of a single application. Thus a DLL that is used by a Delphi and a C application will exist two times in memory. (Well, not completely, the code sections are shared, all data in the DLL exists twice.) So basically your DLL cannot simply share data between two processes.
There are exceptions, of course. For example, a keyboard hook could be created in a single DLL which is loaded in your Delphi application, then injected into the address space of the C process. Then the DLL can 'peek' into the memory space of the C application and capture some information. (Keyboard events with KeyHooks.) But KeyHooks and similar injectable DLL's will be noticed as "bad" by the average antivirus product. And for good reason, because this is behaviour you'd expect from a computer virus.
Another solution instead of IPC would be the use of a memory mapped file. There are several components available as open-source or commercially but you can also use the Windows API to create these.
The Windows API also provides techniques like Named Pipes and MailSlots, which can also be used for interprocess communication. It doesn't need to be TCP/IP but you will need some way for the two processes to communicate with one another. And this logic could indeed be build in a single DLL, where you'd define just two methods. One for the server, one for the client. It is a complicated technique, though. And Delphi 5 is a bit old so I don't know which solution would work best for you.

Workshop Alex
+2  A: 

For the easiest possible IPC try WM_COPYDATA with PostMessage or SendMessage
Microsoft doc:
http://msdn.microsoft.com/en-us/library/ms649011%28VS.85%29.aspx

Microsoft sample:
http://msdn.microsoft.com/en-us/library/ms649009%28v=VS.85%29.aspx

And much more info on google:
http://www.google.com/search?q=WM_COPYDATA&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:pt-BR:official&client=firefox-a

arthurprs
Im trying to use WM_Copydata, but im having problems with the registering the message, in my delphi app, so there might popup another question later to day :)
Roise
Well, you don't need to register the message, only find the target HWND and send it. The WM_COPYDATA message will arrive at the target message queue.
arthurprs