Click here to Skip to main content
15,881,882 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
Hi, Let me try to explain my problem here.

I have a DLL, it is written in C++. It monitors all print objects for incoming print jobs (Through a Thread)and then fetch some information from print details. Upto here it is OK. Now I have to send this information to delphi project who loaded this C++ DLL.

I am really clueless how can I make this communication happen

Let the c++ code has following functionality:
Initialize or start monitoring print objects (starts thread)
if any print job comes, asome information is fetched
Now I have to send back this info to that Delphhi code who is waiting for it.

Let the Delphi code is like below:
[DELPHI CODE]
Load DLL;
Wait for message
Unload DLL

Can any one give me any overall all idea. No need to tell me the code but some mechanism is needed.

update:
Is use of share memory is that solution?
Thanks.
Posted
Updated 21-Mar-13 8:08am
v2

If you have the source to both parts, C++ and Delphi and you build both with C++ Builder/Rad Studio then you can call the C++ code from the Delphi and the other way around too.
In that case you could do what you want with a callback. You pass the address of a Delphi function into the C++ as a function pointer parameter. Then call the Delphi function using that pointer when the C++ has a message to send back.
It may sound complicated but it's a lot simpler than shared memory.
Your C++ Builder/Rad Studio should have samples for calling one kind of code from the other, add a little google research into C++ function pointers and you should be able to make it work.
 
Share this answer
 
Comments
Espen Harlinn 21-Mar-13 16:11pm    
5'ed! :-D
Matthew Faithfull 21-Mar-13 19:27pm    
Thanks very much. COM would of course work equally well.
Sergey Alexandrovich Kryukov 21-Mar-13 20:18pm    
Fair enough, my 5. COM should rather be considered absolute, but COM interfaces (especially implemented via IDL), and their implementations are compatible and can be used very well, to introduce OOP-style DLL import/export compatible with both languages. I did it the way it was compatible with Unix...
—SA
Maxim Kartavenkov 22-Mar-13 5:19am    
Your solution just copy of mine, but there is require to have dll to be compiled in C++ Builder.
Matthew Faithfull 22-Mar-13 5:26am    
No not a copy, I'm not suggesting shared memory just a normal DLL interface and yes both the C++ and the Delphi need to be build with the same calling conventions and name mangling scheme to ensure that a call interface will work. The easiest and best way to do this is build both with the same compiler suite so that you can be sure it can work. Otherwise you never know. Try calling a 5 parameter function in a DLL built with GCC from an EXE built with MSVC even though are C++ on Windows and you'll likely see what I mean. Bang, crunch, splat :-(
Assuming you're using Visual C++, you could use COM, here is a pretty nice tutorial: A Beginner Tutorial for Writing Simple COM/ATL DLL For VS2012[^]

Delphi works pretty well with COM, so accessing the COM object should be quite easy.

Best regards
Espen Harlinn
 
Share this answer
 
Comments
Maciej Los 21-Mar-13 15:56pm    
+5!
Espen Harlinn 21-Mar-13 16:13pm    
Thank you, Maciej :-D
Sergey Alexandrovich Kryukov 21-Mar-13 20:20pm    
My 5, but I don't know what exactly do you mean by COM. Please see my comment to Solution 2. I think the best way of using COM is when you avoid using windows COM API (and contaminating the registry) at all. COM used to be an OOP patch to non-OOP OS...
—SA
Espen Harlinn 21-Mar-13 20:50pm    
Delphi relies on correct component registration, which IMHO isn't a bad thing ...

Many people consider COM and CORBA to be obsolete, but in my view w3c based technologies has a long way to go before they match either of them.

While neither of the technologies are dead, they require a fair level of skill. Implementing someting similar to a WCF service is trivial when you use either of them, it's when you expose objects, that has among other things a lifetime, that many developers had trouble keeping up.

COM is a fundamental part of Windows, and MS keeps adding new APIs' based on COM to the operating system.

The biggest problem with COM and the registry is 'lazy' system administrators that can't be bothered to either use the installation programs provided with a solution or actually figure out how this actually works. The problem is that many sysadmins tries to modify how the installation is supposed to work - there probably aren't any 'sane' reasons for this, in 99 out of 100 scenarios they should just do a full installation of the software, and install software and patches in the order of their release date. It's when they don't follow this very simple procedure that they run into problems, and instead of taking the resposibility for their own shortcommings they blame the technology.
Sergey Alexandrovich Kryukov 21-Mar-13 20:57pm    
Well, I understand all that, many good points here. It all depends on what do you consider "obsolete". Morally obsolete. Windows is obsolete, in this sense. It's a dead end. Windows 8 is especially sad, due to certain revival of COM, in particular...
Anyway, direct use of exported functions (perhaps with COM interfaces as I tried to explain in my comments) for language interop (also obsolete), is the clearer way. How to explain that? Due to less multiplication of evil in the world... :-)
—SA
C++
C++ DLL: "MyDll.dll"
/////////////////////////////////////////////////////
typedef HRESULT (CALLBACK * CALLBACKPROC)(DWORD wEvent,LONG_PTR arg,PVOID pParam);
/////////////////////////////////////////////////////
CALLBACKPROC g_pCallback = NULL;
LPVOID g_pCallbackParam = NULL;
/////////////////////////////////////////////////////
EXTERN_C VOID __declspec(dllexport) WINAPIV SetCallback(CALLBACKPROC _proc,LPVOID pParam)
{
g_pCallback = _proc;
g_pCallbackParam = pParam;
}
/////////////////////////////////////////////////////
#define SOMEDLLMETHOD_EVENT_ID 0x01
/////////////////////////////////////////////////////
EXTERN_C VOID __declspec(dllexport) WINAPIV SomeDllMethod()
{
if (g_pCallback) g_pCallback(SOMEDLLMETHOD_EVENT_ID,(LONG_PTR)"some argument",g_pCallbackParam);
}
/////////////////////////////////////////////////////
// Delphi wrapper with dynamic DLL linkage:
/////////////////////////////////////////////////////
type
TDllWrapper = class
protected
FOnDllEvent: TNotifyEvent;
m_hDll: HMODULE;
protected
function OnCallbackEvent(wEvent:DWORD;arg:Pointer):HRESULT; virtual;
public
procedure CallSomeDllMethod();
public
constructor Create;
destructor Destroy;
published
property OnDllEvent: TNotifyEvent read FOnDllEvent write FOnDllEvent;
end;
 
type
TCALLBACKPROC = function(wEvent:DWORD;arg:Pointer;pParam:Pointer):HRESULT stdcall;
type
TSetCallbackFunc = procedure(_proc:TCALLBACKPROC;pParam:Pointer) cdecl;
 
const SOMEDLLMETHOD_EVENT_ID = $01;
 
function CallbackProc(wEvent:DWORD;arg:Pointer;pParam:Pointer):HRESULT stdcall;
begin
result := 0;
if (pParam <> nil) then result := TDllWrapper(pParam).OnCallbackEvent(wEvent,arg);
end;

constructor TDllWrapper.Create;
var
fnSetCallback:TSetCallbackFunc;
begin
inherited Create;
m_hDll := LoadLibrary('MyDll.dll');
fnSetCallback := GetProcAddress(m_hDll,'SetCallback');
fnSetCallback(CallbackProc,self);
end;
 
destructor TDllWrapper.Destroy;
var
fnSetCallback:TSetCallbackFunc;
begin
fnSetCallback := GetProcAddress(m_hDll,'SetCallback');
fnSetCallback(nil,nil);
FreeLibrary(m_hDll);
inherited Destroy;
end;
 
function TDllWrapper.OnCallbackEvent(wEvent:DWORD;arg:Pointer):HRESULT;
begin
result := 0;
if (wEvent = SOMEDLLMETHOD_EVENT_ID) then
begin
if Assigned(FOnDllEvent) then FOnDllEvent(self);
end;
end;

procedure TDllWrapper.CallSomeDllMethod();
var
fnSomeDllMethod:procedure() cdecl;
begin
fnSomeDllMethod := GetProcAddress(m_hDll,'SomeDllMethod');
fnSomeDllMethod();
end;
/////////////////////////////////////////////////////
// Example of usage:
/////////////////////////////////////////////////////
type
TMainForm = class(TForm)
m_MyDll:TDllWrapper;
procedure OnDllEventCallback(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);

end;
 
procedure TMainForm.OnDllEventCallback(Sender: TObject);
begin
OutputDebugString('Our callback event called');
end;
 
procedure TMainForm.FormCreate(Sender: TObject);
begin
m_MyDll:= TDllWrapper.Create;
m_MyDll.OnDllEvent := OnDllEventCallback;
m_MyDll.CallSomeDllMethod;
end;
 
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
m_MyDll.Free;
end;


[edit]code block added[/edit]
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900