2017-12-13 19 views
1
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); 

をデルファイするC/C++コールバックfunctonを変換する:どのように私はこのようなdefinetions上で変換

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; 

私は、Delphiに変換するC/C++ DLL関数を知っているが、コールバックは私のために新しく追加されました。 私の定義は正しいですか?

+3

C、C++のどの言語ですか?彼らは異なる言語です。たとえば、C++にはオペレータと関数のオーバーロードがあり、名前のマングリングが発生する可能性があります。 –

+0

Cの関数はcdeclのように見えます –

答えて

2

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; 

あなたのコードから、最も重要な違いがof objectとして宣言されていないTPaymentResultCallbackです。 Cスタイルの関数ポインタとしてDelphiスタイルのメソッドポインタを使用することはできません。つまり、少なくともこの例では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です。

+0

私はどれが好きですか?使い方はどうですか?申し訳ありませんが、私は混乱しています。どうもありがとうございました。 – ErkanK

+0

@ErkanKあなたが好むものはあなた次第です。あなたの状況に適したものを使用してください。 –

+0

私はあなたの定義を昨日試みましたが、私は自分の問題を解決できませんでした。まず第一に、私は第二の敗北を試みた。私はいつも始まるmyPaymentResultCallback関数で "Access Vioaltion"エラーが出ます。だから私の問題は解決しませんでした。しかし、私はこのdefinationが大好きです:)最初のdefinationは、常にデバッガ "変数が必要"と私に言ったことです。では、この状況での私のせいは何ですか? – ErkanK

関連する問題