如何将c/c++回调函数转换为delphi
Posted
技术标签:
【中文标题】如何将c/c++回调函数转换为delphi【英文标题】:How to convert c/c++ callback functon to delphi 【发布时间】:2017-12-13 21:29:39 【问题描述】: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,但回调对我来说是新的。 我的定义正确吗?
【问题讨论】:
哪种语言,C 或 C++?它们是不同的语言。例如,C++ 有运算符和函数重载,这可能会导致名称混乱。 C 函数看起来像 cdecl 【参考方案1】:您的 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每次调用不同的方法。
IF DLL 提供了一种将用户定义的值与回调相关联的方法(并且您的示例似乎没有该选项,除非为此目的有单独的 DLL 函数),事情变得更容易。您可以简单地将实际方法指针作为该用户定义的值传递(指向),然后您的私有回调函数可以直接调用它。不需要全局变量,使其可重入多个事件并行运行。但这是一个很大的IF。
【讨论】:
那么我更喜欢哪一个,它的用法如何?对不起,我很困惑。非常感谢。 @ErkanK 你喜欢哪一个取决于你。使用适合您情况的任何一种。 我昨天尝试了你的定义,但我仍然无法解决我的问题。首先,我尝试了第二个定义。我总是在开始时在 myPaymentResultCallback 函数中收到“访问冲突”错误。所以它没有解决我的问题。但我喜欢这个定义。:) 第一个定义是总是用调试器说我“需要变量”。那么在这种情况下我的错是什么 对不起。对不起。这是我的错。您的第二个解决方案对我来说是正确的。问题是“cdecl”。在我的示例中,我忘记将它用于 myPaymentResultCallback 函数。再次感谢您以上是关于如何将c/c++回调函数转换为delphi的主要内容,如果未能解决你的问题,请参考以下文章