簡體   English   中英

GTK / C在功能之間共享數據和變量

[英]GTK/C sharing data and variables between functions

問題是:在功能之間共享數據的最佳方法是什么,特別是在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();
//...
}

您應該對全局變量保持警惕,特別是如果您只想允許某些函數修改它們時,您是對的。

假設您保留的數據不只是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將在本地范圍內。 我假設將使用“ clicked”事件為某些按鈕設置回調。

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 ,則可以類似的方式傳遞該值,而無需結構。

如果要使用全局變量,只需使用全局變量。 而且,無論世界怎么說,沒人會因為使用過全球性物品而死亡。

避免使用全局變量,因為這樣會使大型程序難以維護,而且從您的描述來看,情況似乎並非如此。

在共享方面,GTK +程序通常不是並行的,因此您可以在RW中自由訪問全局變量而不會出現問題。 同樣,當使用任務時,最佳做法是將所有GTK +調用置於同一任務上:仍然允許您從同一任務訪問RW中的全局變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM