動的リンクしたDLLの関数の引数にコールバック関数を指定するには?

解決


こぶた  2012-01-23 19:42:32  No: 73155  IP: 192.*.*.*

提供されたDLLを動的リンクして自EXE内で使用するのですが、DLLの関数で引数に自EXE内の関数をコールバック関数として指定するものがあります。
自EXE側での記述方法がわからず困っています。

<DLLのヘッダ>
#define ACS_FUNC_START_ASYNC _T("ACS_Start_Async")
//*** 処理結果通知コールバック関数
typedef void (CALLBACK *ACS_START_CB)(LPVOID pUserInfo, DWORD dwStartResult, LPACS_ERR_INFO pstErrInfo);
//*** アクセス開始処理関数
typedef DWORD (APIENTRY *ACS_FP_START_ASYNC)(
        ACS_START_CB, // 処理結果を通知するコールバック関数のアドレス
        LPVOID, // コールバック関数呼び出し時に渡す引数
        LPACS_ERR_INFO); // エラー情報

<EXE側ヘッダ>
ACS_FP_START_ASYNC ACS_Start_Async;
void AcsLibErrLogout(LPACS_ERR_INFO *AcsErrInfo);

<EXE側プログラム>
void AcsLibErrLogout(LPACS_ERR_INFO *AcsErrInfo)
{
   .... // 処理省略
}

int test(){
   HMODULE m_hDll = LoadLibrary(XXX.dll);
   ACS_Start_Async = (ACS_FP_START_ASYNC)GetProcAddress(m_hDll, ACS_FUNC_START_ASYNC);
   ACS_START_CB AcsStartCB = &AcsLibErrLogout;
   ACS_ERR_INFO AcsErrInfoCB;
   ACS_ERR_INFO AcsErrInfo;
   DWORD dwRet;
   dwRet = ACS_Start_Async(AcsStartCB, &AcsErrInfoCB, &AcsErrInfo);
}

と記述したところ、最終行のところでコンパイルエラー:C2440が発生します。
どのように変更したらいいでしょうか?

編集 削除
こぶた  2012-01-23 19:45:24  No: 73156  IP: 192.*.*.*

開発環境を記述し忘れました。

OS:WindowsXP ServicePack3
VisualStudio2008 ServicePack1 VC++

です。宜しくお願いします。

編集 削除
fuku  2012-01-23 21:56:51  No: 73157  IP: 192.*.*.*

typedefされている通り、
void CALLBACK AcsLibErrLogout(LPVOID pUserInfo, DWORD dwStartResult, LPACS_ERR_INFO pstErrInfo)
の関数を渡さなければいけません。(関数名や引数名は変えても構いません)

このコールバック関数の各引数に何が渡されてきて、何をしなければならないかはそのDLLの資料を見てください。

編集 削除
こぶた  2012-01-24 18:44:53  No: 73158  IP: 192.*.*.*

エラー発生箇所が間違っていました。
int test() 内の3行目  ACS_START_CB AcsStartCB = &AcsLibErrLogout;
の所でした。

fukuさん、回答ありがとうございます。

EXE側のコールバック関数の定義が間違っているのでしょうか?
AcsLibErrLogout関数を
void CALLBACK AcsLibErrLogout(LPVOID pUserInfo, DWORD dwStartResult, LPACS_ERR_INFO pstErrInfo)

という風に定義し直してもエラー発生内容は変わりませんでした。

編集 削除
fuku  2012-01-25 13:15:38  No: 73159  IP: 192.*.*.*

コールバック関数を正しく定義して指定すれば通るはずです。
DLLにある関数がコールバックしてくるといっても、特別に考える必要はありません。
通常のコールバック関数と扱いとしては同じです。

コールバック関数の型としての定義はそれで間違っていないはずなので、
エラーが依然変わらないというのであれば、渡そうとしている関数が見えていないのかもしれません。
コールバック関数を定義している名前空間がtest関数から見えているか、
test関数からコールバック関数を定義している名前空間を参照するまでに同名の何かがないか確認してみてください。

また、C2440が出している「型名」からACS_START_CBへ変換できません、の型名の部分がヒントになるはずです。
エラーメッセージに追加の情報が含まれる場合はそれも提示された方が適切な回答が得やすいと思いますよ。

編集 削除
こぶた  2012-01-25 20:16:52  No: 73160  IP: 192.*.*.*

fukuさん、回答ありがとうございます。
アドバイス通り、エラーメッセージの内容をよく確認したところ
コールバック関数 AcsLibErrLogout をダイアログクラスのメンバ関数として
定義してしまっていました。

void CALLBACK testDlg::AcsLibErrLogout(LPVOID pUserInfo, DWORD dwStartResult, LPACS_ERR_INFO pstErrInfo)
{
}

当たり前ですよね... 単純なミスでした。
上記の tesutDlg:: 部分を削除しビルドしたところエラーはなくなりました。
本当に助かりました。
ありがとうございました。

編集 削除