如何将C/C 回调函数转换为Delphi

How to convert c/c++ callback functon to delphi

本文关键字:转换 Delphi 函数 回调      更新时间:2023-10-16
typedef void (*onPaymentResultCallback) (int result);
DLL_EXPORT int AR_payment_item_credit(const char *terminal_no, const char *description, double amount, enum currency_id cid, int receiptid,
                onPaymentResultCallback cb);

我将上述定义转换为这样:

TonPaymentResultCallback = procedure(result:LongInt) of object;
function AR_payment_item_credit(HInst:THandle; const TerminalNo:PAnsiChar; const Description:PAnsiChar; Amount:Double; CurrencyId:LongInt;
RecepitID:LongInt; onPaymentResultCallback:tonPaymentResultCallback):LongInt;
var
  MyFunct: function (const TerminalNo:PAnsiChar; const Description:PAnsiChar; Amount:Double; CurrencyId:LongInt;
           RecepitID:LongInt; onPaymentResultCallback:tonPaymentResultCallback): LongInt; cdecl;
begin
  Result := 0;
  MyFunct:=GetProcAddress(HInst,'AR_payment_item_credit');
  if Assigned(MyFunct) then
    Result := MyFunct(TerminalNo, Description, Amount, CurrencyId, RecepitID,onPaymentResultCallback);
end;

我知道C/C DLL函数转换为Delphi,但是回调对我来说是新的。我的定义正确吗?

您的delphi翻译中有一些错误。改用此方法:

type
  TPaymentResultCallback = procedure(AResult: Integer); cdecl;
function ARPaymentItemCredit(HInst: THandle; const TerminalNo: PAnsiChar;
  const Description: PAnsiChar; Amount: Double; CurrencyID: Integer;
  ReceiptID: Integer; onPaymentResult: TPaymentResultCallback): Integer;
var
  MyFunct: function(const TerminalNo: PAnsiChar; const Description: PAnsiChar;
    Amount: Double; CurrencyID: Integer; ReceiptID: Integer;
    onPaymentResult: TPaymentResultCallback): Integer; cdecl;
begin
  @MyFunct := GetProcAddress(HInst, 'AR_payment_item_credit');
  if Assigned(MyFunct) then
    Result := MyFunct(TerminalNo, Description, Amount, CurrencyID, ReceiptID, onPaymentResult)
  else
    Result := 0;
end;

与您的代码最重要的区别是TPaymentResultCallback不称为of object。您不能将Delphi风格的方法指针用作C型函数指针,这意味着至少在此示例中,您不能将非静态类方法用于DLL回调。

但是,有一个简单的解决方法 - 将所需的方法指针存储在全局变量中,然后使用私有回调函数来调用它,例如:

type
  TPaymentResultEvent = procedure(AResult: Integer) of object;
var
  gOnPaymentResult: TPaymentResultEvent;
procedure myPaymentResultCallback(AResult: Integer); cdecl;
begin
  if Assigned(gOnPaymentResult) then
    gOnPaymentResult(AResult);
end;
function ARPaymentItemCredit(HInst: THandle; const TerminalNo: PAnsiChar;
  const Description: PAnsiChar; Amount: Double; CurrencyID: Integer;
  ReceiptID: Integer; onPaymentResult: TPaymentResultEvent): Integer;
type
  TPaymentResultCallback = procedure(AResult: Integer); cdecl;
var
  MyFunct: function(const TerminalNo: PAnsiChar; const Description: PAnsiChar;
    Amount: Double; CurrencyID: Integer; ReceiptID: Integer;
    onPaymentResult: TPaymentResultCallback): Integer; cdecl;
begin
  @MyFunct := GetProcAddress(HInst, 'AR_payment_item_credit');
  if Assigned(MyFunct) then
  begin
    gOnPaymentResult := onPaymentResult;
    Result := MyFunct(TerminalNo, Description, Amount, CurrencyID, ReceiptID, @myPaymentResultCallback)
  end
  else
    Result := 0;
end;

不必说,如果您需要同时呼叫ARPaymentItemCredit()的多个类,因此要求DLL每次调用不同的方法。

如果 dll提供了一种将用户定义值与回调相关联的方法(您的示例似乎没有该选项,除非为此目的有单独的DLL功能),变得容易。您可以将实际方法指针作为用户定义的值传递(指向指针),然后您的私人回调函数可以直接调用。不需要全局变量,因此可以重新进入多个事件,以并行运行。但这是一个大,如果