0

コードHello World In GTKをこのリンクから取得しました。そこでは多くのコールバック関数を使用しますが、各コールバック関数について言う

static void hello( GtkWidget *widget,gpointer data )

それをコールバックとして使用すると、

g_signal_connect (button, "clicked",G_CALLBACK (hello), NULL);

ただし、ここでは hello() 関数に引数を渡していません。通常の関数でこれを実行しようとすると、つまり

#include <stdio.h>
int hello(int a) {
   printf("hello");
}

void main() {
   int j=10;
   hello;
}

エラーも出力もありません。

Q1. コールバック関数が引数を無視するのはなぜですか?

Q2. 関数コールバックを作成するには? つまり、私の 2 番目helloの例では、関数 hello はコールバックになりますか?

4

3 に答える 3

1

こんにちはと言うのは int 値に言及するのと同じなので、コードはコンパイルされます。例えば:

hello; // this just writes the function pointer with a ; so it works
12345; // this is similar to the above and will compile

コールバックには、前述のようにマクロを使用して、または接続関数で他の方法でパラメーターが渡されていると想定しています。

于 2013-03-13T22:40:55.610 に答える
1

あなたがしているのは、関数へのポインターを GLib に渡すことによって、関数をシグナルにアタッチすることです。これのポイントは、シグナルがトリガーされたときに関数を呼び出すことです。この場合、それは GTK ボタンが押されたときです。基本的に、これはユーザー アクション (ボタンを押す) を関数にリンクしますが、GTK ボタンを実装するコードが関数について知る必要がない方法でリンクします。

このマクロは、次のように定義されG_CALLBACKている type に関数ポインターをキャストします。GCallback

typedef void (*GCallback)(void);

ドキュメントで説明されているように:

構造体定義と関数シグネチャでコールバック関数に使用される型。これは、すべてのコールバック関数がパラメーターをとらず、void を返さなければならないという意味ではありません。コールバック関数に必要なシグネチャは、使用されるコンテキスト (接続先の信号など) によって決まります。G_CALLBACK() を使用して、コールバック関数を GCallback にキャストします。

GLib がこれを行う理由は、コールバックの型を統一する (そしてマクロで何をしているかを文書化する) ためです。GLib では、さまざまな数のパラメーターを取るコールバックが許可されますが、これらのコールバックをシグナルにアタッチするための共通の一貫したインターフェイスが提供されます。内部的には、GLib は正しい数のパラメーターで関数をディスパッチします。

関数ポインターの詳細については、この SO の質問を参照してください:関数ポインターのポイントは何ですか?

于 2013-03-13T22:48:18.190 に答える
0

G_CALLBACK はマクロだと思います。(マクロはコンパイル前にプリプロセッサによって展開されるため、無効な C のように見えるものは、多くのマクロを使用している可能性があります。) このマクロが展開される内容を確認する必要があります。コードが何をしているのかを理解するのに役立ちます。

ちなみに、関数ポインタを(関数のアドレスを取得するなどして&hello)別の関数に渡し、その関数でそれを呼び出したい場合は、次のようにします。(*function)(arg,arg2)

于 2013-03-13T22:29:10.057 に答える