1

问题是:在函数之间共享数据的最佳方式是什么,尤其是在 GTK/C 应用程序中?最好意味着最“合适”、运行速度最快和/或吸收尽可能低的 CPU 功率。
我问是因为我必须在 linux 下使用 GUI 编写一些应用程序,但我是一个微控制器程序员(也许我很难像大型计算机一样思考)。在小型 8 位 MCU 的世界中,代码是纯 C 语言,全局变量是在函数之间共享数据的最快和常用的方式。
但我想,在操作系统下运行的更复杂的应用程序中,必须有其他“特殊”方式来做到这一点。至此,我注意到 GTK(GDK、Glib 等)提供了许多特殊功能和内置机制,使程序员的生活更轻松,所以我认为在函数之间共享变量应该是一种优雅的方式。在网上搜索我看到了不同的解决方案:
- 具有私有变量的类和获取/设置它们的方法 - 但我的应用程序是用 C 编码的,而不是 C++,我想避免使用对象编程,
- 全局结构甚至一个具有许多成员的大型全局结构,
- 良好的普通全局变量,
- GtkClipboard,但我认为它用于不同的目的。

我想做的只是在一个回调函数中设置一些变量'A',在第二个回调中再次设置该变量,然后在另一个回调中根据变量'A'的值做一些事情,如下所示:

callback_func1{
//...
A = some_func();
//...
}
callback_func2{
//...
A = another_func();
//...
}
callback_func3{
//...
if(A>threshold) do_something();
else do_nothing();
//...
}
4

2 回答 2

2

您对全局变量保持警惕是正确的,特别是如果您只想允许某些函数修改它们。

假设您保留的数据不仅仅是A(为简单起见,我将其定义为int),您可以以熟悉的方式设置您的结构

typedef struct t_MYCBSD
{
    int A;
    // other members
} MYCBSD; // callback struct data

必要时包括其他数据成员。(我已经包括了t_MYCBSD,以防有一些自我引用)。

然后,您可以按如下方式实现回调函数:

void callback_func1( GtkWidget *widget, gpointer user_data )
{
    MYCBSD *data = user_data;
    data->A = some_func();
}

void callback_func2( GtkWidget *widget, gpointer user_data )
{
    MYCBSD *data = user_data;
    data->A = another_func();
}

void callback_func3( GtkWidget *widget, gpointer user_data )
{
    MYCBSD *data = user_data;

    if( data->A > threshold ) do_something();
    else do_nothing();
}

显然,、 、some_func()another_func()在这种情况下是有效的。thresholddo_something()do_nothing()

注意:指向结构的data指针使语法更加清晰。您还可以使用:

((MYCBSD *) user_data)->A = some_func();

无论如何,您通常在创建小部件时设置回调。在以下(大量剔除,非 GtkBuilder)代码中,MYCBSD mydata将在本地范围内。我假设将为某些带有“单击”事件的按钮设置回调。

int main( int argc, char* argv[] )
{
    MYCBSD mydata;
    // Below-referenced widgets
    GtkWidget *mywidget1, *mywidget2, *mywidget3;
    // ... other widgets and variables

    mydata.A = 0;   // Optionally set an initial value to A

    // Standard init via gtk_init( &argc, &argv );

    // ... Create the toplevel and a container of some kind

    // Create mywidget1,2,3 (as buttons, for example)
    mywidget1 = gtk_button_new_with_label ("widget1");
    mywidget2 = gtk_button_new_with_label ("widget2");
    mywidget1 = gtk_button_new_with_label ("widget3");

    g_signal_connect( mywidget1, "clicked", G_CALLBACK(callback_func1), &mydata );
    g_signal_connect( mywidget2, "clicked", G_CALLBACK(callback_func2), &mydata );
    g_signal_connect( mywidget3, "clicked", G_CALLBACK(callback_func3), &mydata );

    // ... Attach those widgets to container
    // ... and show all

    // Run the app in a standard way via gtk_main();

    return 0;
}

这里的重要行是:

    g_signal_connect( mywidget1, "clicked", G_CALLBACK(callback_func1), &mydata );
    g_signal_connect( mywidget2, "clicked", G_CALLBACK(callback_func2), &mydata );
    g_signal_connect( mywidget3, "clicked", G_CALLBACK(callback_func3), &mydata );

最后一个参数将您的数据传递给回调函数。

如果您只想共享一个值,A则可以以类似的方式传递它,而无需结构。

于 2014-10-01T21:56:57.160 回答
0

如果要使用全局变量,只需使用全局变量。而且,不管世界怎么说,没有人因为使用了全局变量而死。

避免使用全局变量是因为很难对大型程序进行维护,并且根据您的描述,情况似乎并非如此。

在共享方面,GTK+ 程序通常不是并行的,因此您可以毫无问题地在 RW 中自由访问全局变量。而且,当使用任务时,最好将所有 GTK+ 调用放在同一个任务上:您仍然可以从同一个任务访问 RW 中的全局变量。

于 2014-10-05T08:03:27.233 回答