関数ポインタのみ!(ながせろぐ)とか、Visual Basic でなんとなくイベントとデリゲート その4。 - デリゲートとは? -(とりこびと ぶろぐ。)とか、より。
いまね、使ってるですよ、C で。
この辺、MONITOR2(Windows Driver Kit: Print Devices)とか、見ていただきましょうかね。
typedef struct _MONITOR2 {
DWORD cbSize;
BOOL (WINAPI *pfnEnumPorts)
(HANDLE hMonitor, LPWSTR pName, DWORD Level, LPBYTE pPorts
, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
BOOL (WINAPI *pfnOpenPort)
(HANDLE hMonitor, LPWSTR pName, PHANDLE pHandle);
BOOL (WINAPI *pfnOpenPortEx)
(HANDLE hMonitor, HANDLE hMonitorPort, LPWSTR pPortName
, LPWSTR pPrinterName, PHANDLE pHandle
, struct _MONITOR2 FAR *pMonitor2);
(長いので省略)
} MONITOR2, *PMONITOR2, FAR *LPMONITOR2;
見事に、関数ポインタだけです。あ...今気がついた。LPWSTR じゃないか。W 固定かよ。。。そか。動いてるモンな。
こいつは、開発者が「ポートの一覧」「ポートの情報取得」などをするときにはこの関数を呼び出して下さい、とスプーラ サービスに登録するための構造体です。ユーザがプリンタのプロパティを開いたりすると、アプリケーションから「このポートの一覧を出す関数を呼び出してくれ」という連絡がスプーラに渡り、スプーラが登録されている内容を元にポート モニタ DLL 内の関数を呼び出します。
あとは、あれだ。長い処理をする間に、要所要所で何かを実行して欲しいときに使ったりしますね。
C# などではイベントを使えばいいのですが、昔は「コールバック関数」とかって、関数を呼ぶときに関数へのポインタを引数に渡していました。
/* 中断の判断 */
BOOL isInterrupt(void* data)
{
return (data == NULL) ? TRUE : FALSE;
}
/* 中断したいことがある長い処理 */
void someFunction((checkInterrupt*)(void*), void* someData)
{
...
while (!checkInterrupt(checkData)) {
...
}
...
}
main()
{
...
someFunction(isInpterrupt, data_for_function);
...
}
MFC でも、「イベント」は関数ポインタですね。最初にメッセージと関数ポインタのセットを定義して、メッセージを受けたときに組み合わせを元に、定義した関数を呼び出してくれています。
qsort 関数に渡すのも、関数ポインタですね。比較をするための関数を通知します。これって、まんま「デリゲート」ですね。
そんなわけで、デリゲートって、昔から使っていたんですね。
ここまで書いて、ながせさんところのエントリのコメントを読む。はげしくがいしゅつ(なぜか変換でき…てしまうけど変換しない)でした。。。
じゃぁ、なぜアップするのか。
オブジェクト指向言語を、「難しいから」と敬遠する人がいます。そういう人に、知って欲しいと思います。難しくなんかない、ということ。実は、すでに使っていることなんだよ、ということ。
投稿日時 : 2007年10月30日 21:38