如何在 arch linux 系统上使用 glade ang geany ide 连接信号以在 gtk+-3.0 应用程序中处理?

How to connect signals to handle in gtk+-3.0 application, using glade ang geany ide's on arch linux system?

我尝试使用 glade 和 geany ide 制作简单的应用程序,但无法将在 glade 中设置的信号连接到我的处理程序。我用这个命令来构建:

“短”版本:

gcc -Wall -w -g `pkg-config --cflags gtk+-3.0 gmodule-2.0 gmodule-export-2.0` -o "%e" "%f" `pkg-config --libs gtk+-3.0 gmodule-2.0 gmodule-export-2.0`

完整命令:

gcc -Wall -w -g -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/libpng16 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/lzo -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/gio-unix-2.0 -I/usr/include/cloudproviders -I/usr/include/atk-1.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -I/usr/include/at-spi-2.0 -pthread -o "%e" "%f" -lgtk-3 -lgdk-3 -lz -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -Wl,--export-dynamic -lgmodule-2.0 -pthread -lglib-2.0 -lglib-2.0

我的代码(基于俄语教程):main.cpp

#include <stdio.h> 
#include <gtk/gtk.h>
#include <string.h>
#include <stdlib.h>
#include <libintl.h>
#include <locale.h>
#include <locale>
#include <cstdlib>

//main gtk objects
using namespace std;
/* это тот волшебный объект, который сделает за нас окошко */
GtkBuilder *builder;

/* это виджет окна */
GtkWidget *window;

//function to quit the app without data corruption
void safe_quit (GtkWidget* object, gpointer data)
{
        gtk_main_quit();
}

void click (GtkButton *button, gpointer label)
{
        /* установить метке текст */
        gtk_label_set_text ((GtkLabel*)label, "Привет, Хабр!");
}

/* создание окна в этот раз мы вынесли в отдельную функцию */
static GtkWidget* create_window (void)
{
        
        /* сюда будем складывать ошибки */
        GError* error = NULL;

        /* тут загружаем файл с интерфейсом */
        builder = gtk_builder_new ();
        
        //gtk_builder_set_translation_domain(builder,"ru");
        if (!gtk_builder_add_from_file (builder, "glade1.glade", &error))
        {
                /* загрузить файл не удалось */
                g_critical ("Не могу загрузить файл: %s", error->message);
                g_error_free (error);
        }

        /* получаем виджет окна, чтобы его показать */
        window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
        if (window == NULL)
        {
                /* что-то не так, наверное, ошиблись в имени */
                g_critical ("Ошибка при получении виджета окна");
        }
        
        //g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(safe_quit), NULL);
        
        /* помните, мы подключали сигналы вручную? теперь это происходит автоматически! */
        gtk_builder_connect_signals (builder, NULL);
        gtk_builder_connect_signals (builder, window);
        g_object_unref (builder);
        return window;
}
int main (int argc, char **argv)
{       
        setlocale(LC_ALL, "");
        auto lang = "";
        bindtextdomain(lang, "./locale");
        textdomain(lang);
        //std::cout << gettext("hello, world!") << std::endl;
        auto _ = gettext;
        printf(_("help"));
        
        /* виджет окна */
        GtkWidget *window;
        /* запускаем GTK+ */
        gtk_init (&argc, &argv);
        
        /* вызываем нашу функцию для создания окна */
        window = create_window();
        
        gtk_widget_show (window);
        gtk_window_set_title (GTK_WINDOW(window), "main");
        /* передаём управление GTK+ */
        gtk_main ();
       // printf("f");
        return 0;
}

我的空地文件:glade1.glade

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.38.2 -->
<interface>
  <requires lib="gtk+" version="3.24"/>
  <object class="GtkApplicationWindow" id="window">
    <property name="can-focus">False</property>
    <property name="default-width">440</property>
    <property name="default-height">250</property>
    <signal name="destroy" handler="safe_quit" after="yes" swapped="no"/>
    <child>
      <object class="GtkBox" id="box1">
        <property name="visible">True</property>
        <property name="can-focus">False</property>
        <property name="orientation">vertical</property>
        <child>
          <object class="GtkMenuBar">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <child>
              <object class="GtkMenuItem">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="label" translatable="yes">_File</property>
                <property name="use-underline">True</property>
                <child type="submenu">
                  <object class="GtkMenu">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-new</property>
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <property name="use-underline">True</property>
                        <property name="use-stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-open</property>
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <property name="use-underline">True</property>
                        <property name="use-stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-save</property>
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <property name="use-underline">True</property>
                        <property name="use-stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-save-as</property>
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <property name="use-underline">True</property>
                        <property name="use-stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkSeparatorMenuItem">
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-quit</property>
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <property name="use-underline">True</property>
                        <property name="use-stock">True</property>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkMenuItem">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="label" translatable="yes">_Edit</property>
                <property name="use-underline">True</property>
                <child type="submenu">
                  <object class="GtkMenu">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-cut</property>
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <property name="use-underline">True</property>
                        <property name="use-stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-copy</property>
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <property name="use-underline">True</property>
                        <property name="use-stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-paste</property>
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <property name="use-underline">True</property>
                        <property name="use-stock">True</property>
                      </object>
                    </child>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-delete</property>
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <property name="use-underline">True</property>
                        <property name="use-stock">True</property>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
            </child>
            <child>
              <object class="GtkMenuItem">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="label" translatable="yes">_View</property>
                <property name="use-underline">True</property>
              </object>
            </child>
            <child>
              <object class="GtkMenuItem">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="label" translatable="yes">_Help</property>
                <property name="use-underline">True</property>
                <child type="submenu">
                  <object class="GtkMenu">
                    <property name="visible">True</property>
                    <property name="can-focus">False</property>
                    <child>
                      <object class="GtkImageMenuItem">
                        <property name="label">gtk-about</property>
                        <property name="visible">True</property>
                        <property name="can-focus">False</property>
                        <property name="use-underline">True</property>
                        <property name="use-stock">True</property>
                      </object>
                    </child>
                  </object>
                </child>
              </object>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">0</property>
          </packing>
        </child>
        <child>
          <object class="GtkAspectFrame">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="label-xalign">0</property>
            <property name="shadow-type">none</property>
          </object>
          <packing>
            <property name="expand">True</property>
            <property name="fill">True</property>
            <property name="position">2</property>
          </packing>
        </child>
        <child>
          <object class="GtkSeparator">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <property name="margin-top">2</property>
            <property name="margin-bottom">2</property>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">3</property>
          </packing>
        </child>
        <child>
          <object class="GtkBox">
            <property name="visible">True</property>
            <property name="can-focus">False</property>
            <child>
              <object class="GtkLabel">
                <property name="visible">True</property>
                <property name="can-focus">False</property>
                <property name="label" translatable="yes">status: normal</property>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">0</property>
              </packing>
            </child>
            <child>
              <object class="GtkButton">
                <property name="label" translatable="yes">button</property>
                <property name="visible">True</property>
                <property name="can-focus">True</property>
                <property name="receives-default">True</property>
                <signal name="clicked" handler="click" object="__glade_unnamed_23" swapped="no"/>
              </object>
              <packing>
                <property name="expand">False</property>
                <property name="fill">True</property>
                <property name="position">1</property>
              </packing>
            </child>
            <child>
              <placeholder/>
            </child>
          </object>
          <packing>
            <property name="expand">False</property>
            <property name="fill">True</property>
            <property name="position">4</property>
          </packing>
        </child>
      </object>
    </child>
  </object>
</interface>

当我尝试启动我的应用程序时,我总是收到这 3 条消息:

(main:32570): Gtk-WARNING **: 17:41:09.237: Could not find signal handler 'safe_quit'. Did you compile with -rdynamic?

(main:32570): Gtk-WARNING **: 17:41:09.237: Could not lookup object __glade_unnamed_23 on signal clicked of object ___object_24

(main:32570): Gtk-WARNING **: 17:41:09.237: Could not find signal handler 'click'. Did you compile with -rdynamic?

我在 Whosebug 上阅读了很多相同的问题,但没有任何帮助。我更改了处理程序参数、名称、添加静态和 G_MODULE_EXPORT,但所有这些都不起作用。

this site 上,我发现这个“在 Linux 和 Unices 上,这不是必需的 (G_MODULE_EXPORT);应用程序应该使用 -Wl,--export-动态 CFLAGS,并链接到 gmodule-export-2.0。”但是我的应用程序是用 -Wl 和 --export-dynamic 编译的!!!我做错了什么???请任何知道答案或有同样问题的人帮助我找到任何可能的解决方案。

抱歉我的英语不好,感谢您的关注...

P.S。 (找到某种解决方案):

gtk_builder_add_callback_symbol(builder,"safe_quit",G_CALLBACK(safe_quit));
gtk_builder_add_callback_symbol(builder,"click",G_CALLBACK(click));
gtk_builder_connect_signals (builder, NULL);

是否有任何解决方案如何在不使用 gtk_builder_add_callback_symbol 的情况下连接处理程序?我的意思是 gtk_builder_connect_signals 用于自动连接信号以使用 GModule 来处理以查看应用程序的符号 table,所以我的应用程序符号 table 有什么问题不能自动连接信号?

我必须自己编译你的源代码才能使用它,但你似乎在你的程序中混合了 C 和 C++ 语句,这导致 GCC 将它编译为 C++ 文件,就像你在使用g++ 而不是 gcc。 编辑:实际上它会因为你命名了你的文件:“main .cpp”.

反过来,C++ 修饰 函数原型,因此您可以选择性地重载它们,这样纯 C 库将无法在 运行 时找回它们。

将您的信号头原型包含在 extern "C" 块中似乎有帮助:

extern "C"
{

    //function to quit the app without data corruption
    void safe_quit (GtkWidget* object, gpointer data)
    {
            gtk_main_quit();
    }
    
    void click (GtkButton *button, gpointer label)
    {
            /* установить метке текст */
            gtk_label_set_text ((GtkLabel*)label, "Привет, Хабр!");
    }

}