-2

Calling a callback function in Delphi from a C++ DLL

I am sitting with a similar error however my C++ declarations is a little bit different.

typedef int __stdcall CALLBACK(void* pP1, int I1, unsigned char* pUC,
    int I2, int I3, int I4, void* pP2);

which I converted to:

type TCALLBACK = function(var pP1: Pointer; var I1: integer;
    var pUC: PChar; var I2: Integer; var I3: Integer; var I4: Integer;
    var pP2: Pointer): Integer cdecl stdcall;

Function referencing the callback fucntion:

int MyFunction(void* pP1, TCALLBACK* pCallback, void* pP2);

which I converted to:

MyFunction: function(pP1: Pointer; var pCallBack: Pointer;
    pP2: Pointer): Integer cdecl stdcall;

Calling the function:

var P : Pointer;
begin
    //Addr
    P := Addr(PCALLBACK); //had this as @PCALLBACK
    UFS_StartCapturing(ScannerHandle, P, self);
end;

Callback function declared in Delphi as:

function MyCallback(var pP1: Pointer; var I1: integer; var pUC: PChar;
    var I2: Integer; var I3: Integer; var I4: Integer;
    var pP2: Pointer): Integer;
var
    MainForm : TfrmMain;
begin
    //Do your thing
end;

I know my problem lies with the Pointer to the callback (CALLBACK*), and am now trying:

ADRESSOFCALLBACK= ^TCALLBACK;

MyFunction: function(pP1: Pointer; var pCallBack: ADRESSOFCALLBACK;
    pP2: Pointer): Integer cdecl stdcall;

Still not working.

Community
  • 1
  • 1

1 Answers1

3

This

typedef int __stdcall CALLBACK(void* pP1, int I1, unsigned char* pUC, int I2, int I3, 
    int I4, void* pP2);

translates to

type 
  TCALLBACK = function(pP1: Pointer; I1: integer; pUC: PByte; I2, I3, I4: Integer; 
      pP2: Pointer): Integer; stdcall;

You have been mis-using var. Consider the first parameter. That is an untyped pointer. A single level of indirection. You declared it as a pointer, passed by reference. In other words, two levels of indirection.

As for unsigned char*. That's an array of 8 bit values, on presumes. By convention, char is used for text and unsigned char for binary data. So I think that unsigned char* is a byte array.

This

int MyFunction(void* pP1, TCALLBACK* pCallback, void* pP2);

translates to

MyFunction: function(pP1: Pointer; pCallBack: Pointer; pP2: Pointer): Integer; cdecl;

However, it's odd that the callback and the function use different calling conventions. Are you sure that you did not omit a __stdcall in the C++ code?

Now look at how you are calling this:

 var
   P : Pointer;
 begin
   //Addr
   P := Addr(PCALLBACK); //had this as @PCALLBACK
   MyFunction(ScannerHandle, P, self);
 end;

Using Addr and turning the callback into an untyped pointer is a disaster. The compiler can check that you pass a callback with the correct signature. But if you turn the callback into an untyped parameter, the compiler cannot help you. So, write it like this:

 MyFunction(ScannerHandle, MyCallback, self);

where MyCallback is the callback function. I've no idea what PCALLBACK is.

One final point that I cannot stress strongly enough. Your attention to the details here has been very weak. You posted code that did not compile, and used inconsistent names. That is one name in one place, and then the same thing with a different name somewhere else. Interop is all about the details. You must pay much closer attention to them.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • PCALLBACK was supposed to be MyCallback. I had to rename some of the names as the distributor of the header files does not allow for public publishing of their header source code. – StefandB Oct 01 '14 at 16:43
  • When I add MyFunction(ScannerHandle, MyCallback, self) then the compiler gives me E2033 Types of actual and formal var parameters must be identical because it is expecting a Pointer. – StefandB Oct 01 '14 at 17:22
  • Please use the code in my answer. Your error message implies the use of a var parameter in MyFunction. – David Heffernan Oct 01 '14 at 17:54