Watch, Follow, &
Connect with Us

Please visit our new home
community.embarcadero.com.


Welcome, Guest
Guest Settings
Help

Thread: Do callbacks from a 64 bit Delphi DLL to a 64 bit C++ app work?


This question is not answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 1 - Last Post: Feb 10, 2017 10:17 AM Last Post By: Remy Lebeau (Te... Threads: [ Previous | Next ]
Rodney Buckmaster

Posts: 3
Registered: 9/6/02
Do callbacks from a 64 bit Delphi DLL to a 64 bit C++ app work?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 9, 2017 10:34 PM
Has anyone used callbacks successfully from a 64 bit Delphi DLL to a 64 bit C++ app?
We have a 32 bit DLL written in Delphi. It is being called from C++ and Delphi apps successfully. The DLL has a number of simple callbacks defined. When the DLL and apps are compiled as 64 bit, the callbacks work with the 64 bit Delphi app but not the C++ app (access violation occurs). We are using the StdCall calling convention.

E.g.
We have a Delphi DLL with the following exported function that has a callback passed to it:

function AddServer(aServerName: PAnsiChar; aOnReceive: TOnReceiveDataEventStdCall): Cardinal; StdCall;


where the callback is defined as

TOnReceiveDataEventStdCall = procedure(aNetworkMessageHeader: TNetworkMessageHeader;   aNetworkMessageDataPtr: Pointer) of object; StdCall;


The DLL code invokes the callback as follows;

if Assigned(pOnReceiveDataEvent) then  pOnReceiveDataEvent(pHeader, pBuffer);


where
pOnReceiveDataEvent :=  aOnReceive

which assigned in AddServer.


The C++ call to AddServer is

int res = fTAddserver(aServerName, aOnReceive, contextObject);


defined as

typedef ULONG(WINAPI* TAddServer)(char *, TOnReceiveDataEvent, LPVOID);

aOnReceive callback is defined as

typedef void(_stdcall WINAPI *TOnReceiveDataEvent)(LPVOID, TNetworkMessageHeader, LPVOID);

Any ideas what is wrong?

Remy Lebeau (Te...


Posts: 8,905
Registered: 12/23/01
Re: Do callbacks from a 64 bit Delphi DLL to a 64 bit C++ app work?  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Feb 10, 2017 10:17 AM   in response to: Rodney Buckmaster in response to: Rodney Buckmaster
Rodney wrote:

where the callback is defined as

TOnReceiveDataEventStdCall = procedure(aNetworkMessageHeader:
TNetworkMessageHeader;   aNetworkMessageDataPtr: Pointer) of object;
StdCall;

What is TNetworkMessageHeader defined as? Is it a record? If so, how big
is it? IIRC, there is an issue when passing small records (<= 8 bytes) by
value. Consider passing by reference/pointer instead.

Also note that 'of object' is specific to Embarcadero compilers, and will
not work in other compilers. If you ever needed to use your DLL in, say,
a VC++ app, it won't be able to use the callback at all. For true cross-compiler
compatibility, you should get rid of the 'of object'. If the caller needs
access to an object inside the callback, that should be passed around via
a user-defined parameter in the callback.

The C++ call to AddServer is

int res = fTAddserver(aServerName, aOnReceive, contextObject);


defined as

typedef ULONG(WINAPI* TAddServer)(char *, TOnReceiveDataEvent, LPVOID);

That C++ code does not match your Delphi declaration. The Delphi AddServer()
function only has 2 input parameters, but your C++ code is passing 3 values
to it.

aOnReceive callback is defined as

typedef void(_stdcall WINAPI *TOnReceiveDataEvent)(LPVOID, TNetworkMessageHeader, </div>
LPVOID);
<div class="jive-quote">

This also does not match the Delphi declaration. The correct way to deal
with Delphi's 'of object' feature in C++ is to use the '__closure' compiler
extension instead:

typedef void __stdcall (__closure *TOnReceiveDataEvent)(TNetworkMessageHeader, 
void*);


'__closure' is not available in non-Embarcadero C++ compilers.

--
Remy Lebeau (TeamB)

Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02