1

我想将我自己的 gtk 程序从旧的 MinGW 转移到最新的。在过去的 2 周里,我遇到了很多问题,但找不到方法。请参考我发布的其他 2 个问题:

mingw 是否影响编译 gtk 程序在 mingw 中编译 gtk 但失败

最后,我自己编译gtk+2.24.10MinGW. 以下是环境的详细信息:

            GTK version                            gcc version
old mingw   2.10.11 -- from third party            3.4.5
new mingw   2.24.10 -- compiled by myself          4.7.2 or 4.6.2 -- I tried both

对于旧环境下的程序,一切运行良好。

对于新环境下的程序,上面提到的“mingw是否影响编译一个gtk程序”的问题消失了。但是有一个新问题我找不到它来自哪里的任何线索:

启动我的程序时,如果我移动 GUI 窗口,它就会崩溃。我使用 gdb 进行调试,但如果它崩溃了,系统就会冻结。唯一的方法是使用“ctrl + alt + del”来激活任务管理器并停止程序。然后在GDB中,where还是bt full没有显示任何有用的信息。如果我不移动 GUI 窗口,窗口中的所有功能都运行良好。还有一件事,我的程序使用opensslpdflib是来自第三方的。该程序链接到库,但在 GUI 窗口刚启动时不使用它们。

  • 我自己的代码中是否有任何错误?我不这么认为,因为它在旧的 MinGW 环境中运行良好。一些警告g_thread_create, g_thread_init is deprecated在 gtk+2.24.10 包中,但没有出现在 gtk+2.10.11 包中。

  • 是不是我自己在MinGW编译的gtk系统,包括gtk、glib、cario、atk等有什么问题?我说不出来。但是gtk_demo包含在 gtk 包中运行良好,我可以将程序的窗口移动到任何地方。

  • 它与gcc版本有关吗?我说不出来。我google了一下,发现有人抱怨他的gcc 4.7.x编译的gtk程序不稳定,经常受到突然崩溃的影响。gcc 4.6.2 绝对是有人建议的。但就我而言,即使由 gcc 4.6.2 编译,它仍然崩溃。

  • 由于 ABI 问题,它是否与来自第三方的 openssl 和 pdflib 有关?我说不出来。

M代码在Linux环境下编译——gtk+2.24.6。它运行良好。


更新 1

我找到了一些线索。问题来自thread. 但是我仍然不知道为什么它在旧的 MinGW 中有效,但在新的 MinGW 中却失败了。下面是一个简单的例子。

正如我所说,如果我在旧的 MinGW 中编译它,它就可以工作——数据,实际上是一个计数器,在小部件中更新。我可以移动窗口。

如果我在新的 MinGW 中编译它,它就可以工作——数据,实际上是一个计数器,在小部件中更新。但是如果我移动窗口,它就会崩溃。如果我评论了与线程相关的内容,那么我可以移动窗口,但数据不会在窗口中更新。

#include <gtk/gtk.h>

static int counter = 0;
static PangoLayout* layout;
static GdkGC* gc1;
static GdkGC* gc2;
//**/static GMutex* mu;

static gboolean on_expose_event(GtkWidget* widget, GdkEventExpose* event)
{
    gchar the_string[20];

    //**/g_mutex_lock(mu);
    gdk_draw_rectangle(GDK_DRAWABLE(widget->window), gc1, TRUE, 0, 0, widget->allocation.width, widget->allocation.height);
    snprintf(the_string, 20, "%d", counter);
    pango_layout_set_text(layout, the_string, -1);
    gdk_draw_layout(GDK_DRAWABLE(widget->window), gc2, 180, 120, layout);
    //**/g_mutex_unlock(mu);

    g_print (".");
    return FALSE;
}

gpointer func(gpointer data)
{
    //**/g_usleep(10000);
    GdkWindow* window = GDK_WINDOW(data);
    while(TRUE)
    {
  gdk_threads_enter();
        gdk_window_invalidate_rect(window, NULL, FALSE);
gdk_threads_leave();
        //**/gdk_window_process_updates(window, FALSE);
        if(counter % 100 == 0) g_print("X");
        g_usleep(10);
        ++counter;
    }
    return FALSE;
}

int main(int argc, char** argv)
{
    GtkWidget* window;
    GtkWidget* drawer;
    GdkColormap* colormap;
    GdkColor color;

    g_thread_init(NULL);
    gdk_threads_init();
    gtk_init(&argc, &argv);

    //:Create widgets and 
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    drawer = gtk_drawing_area_new();
    gtk_widget_set_size_request(drawer, 400, 300);
    gtk_container_add(GTK_CONTAINER(window), drawer);
    //.

    gtk_widget_show_all(window);

    //:Initializing Graphic Contexts
    colormap = gtk_widget_get_colormap(GTK_WIDGET(drawer));
    layout = gtk_widget_create_pango_layout(GTK_WIDGET(drawer), NULL);
    gc1 = gdk_gc_new(GDK_DRAWABLE(GTK_WIDGET(drawer)->window));
    gc2 = gdk_gc_new(GDK_DRAWABLE(GTK_WIDGET(drawer)->window));
    gdk_color_parse("#000", &color);
    gdk_colormap_alloc_color(colormap, &color, FALSE, TRUE);
    gdk_gc_set_background(gc1, &color);
    gdk_color_parse("#fff", &color);
    gdk_colormap_alloc_color(colormap, &color, FALSE, TRUE);
    gdk_gc_set_foreground(gc2, &color);
    //.

    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect(G_OBJECT(drawer), "expose_event", G_CALLBACK(on_expose_event), NULL);

    //**/mu = g_mutex_new();
    //Run the problematic thread!
    g_thread_create(func, GTK_WIDGET(drawer)->window, FALSE, NULL);

    gdk_threads_enter();
    gtk_main();
    gdk_threads_leave();

    //**/g_mutex_free(mu);
    return 0;
}

编译:

gcc -g -o example update_widget.c `pkg-config --libs --cflags gtk+-2.0 gthread-2.0`

更新 2

我检查config.log了编译glib并找到以下单词:

configure:26678: WARNING: I can't find the MACRO to enable thread safety on your
                platform (normally it's _REENTRANT). I'll not use any flag on
                compilation now, but then your programs might not work.
                Please provide information on how it is done on your system.

它会影响线程功能吗?

我的编译配置glib是:

export CFLAGS="-march=i686"
./configure --prefix=$HOME/gtk+$GTK_VERSION --with-threads=win32 --with-pcre=internal
make
make install
4

0 回答 0