11

私は gtk シグナル コールバック関数が 2 つまたは 3 つの変数を必要とする小さなプログラムを持っています。

私はこれらのグローバル変数を作成したくありません (プロジェクトの全体的な目標はきちんと整理整頓することです)。ウィジェットとコンパイル済みの正規表現を関数に送信できるようにするためだけに、構造体全体を作成したくありません。

私が見たg_signal_connect限りでは、単一のデータ変数しか許可されていません。

これを行う最も効率的な方法は、問題の 2 つのオブジェクトへの void ポインターの配列でしょうか? このようなもの?

void * data[2];
data[0] = widget;
data[1] = compiledregex;
g_signal_connect(save,"clicked",G_CALLBACK(callbackfunction),data);
4

3 に答える 3

9

もちろん、void ポインターの配列を使用できますが、異なる型の値 (特に型が より長い値sizeof(void *)) を渡したい場合は、配列を使用できません。これらの場合、ほとんどの場合、それらを構造体でラップし、構造体のアドレスをデータ パラメーターとして渡します。

例:

struct my_struct *data = malloc(sizeof(*data));
data->field_one = value_one;
data->field_two = value_two; /* etc. */

g_signal_connect(save, "clicked", callback, data);

もちろん、free(data)コールバック関数で を忘れないでください (1 回限りの使用であると仮定します)。

編集: void ** の例が必要だったので、ここにあります (これは醜いので、これを使用することはお勧めしません。プリミティブ型に 1 要素の配列を割り当てると撮影が無駄になるか、キャストが無駄になるためです。 void * への非ポインターは悪い習慣です...):

void **data = malloc(sizeof(data[0]) * n_elements);

type1 *element1_ptr = malloc(sizeof(first_item));
*element1_ptr = first_item;
data[0] = element1_ptr;

/* etc. */

それらを解放するには:

int i;
for (i = 0; i < n_elements; i++)
    free(data[i]);

free(data);
于 2012-08-04T13:11:01.137 に答える
6

g_object_set_data() と g_object_get_data() を使用できます。まず、データを設定します。

g_object_set_data(G_OBJECT(my_edit), "my_label", my_label);
g_object_set_data(G_OBJECT(my_edit), "age", GINT_TO_POINTER(age));

コールバックでは、次のようにデータを取得できます。

gint age = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "age"));
GtkWidget *my_label = g_object_get_data(G_OBJECT(widget), "my_label");
于 2012-08-08T01:59:01.263 に答える