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



我尝试使用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;
}

我的glade文件: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警告**:17:41:09.237:找不到信号处理程序"safe_quit"。你用-rdynamic编译了吗?

(main:32570(:Gtk警告**:17:41:09.237:无法在对象___object_24 的点击信号上查找对象__glade_unnamed_23

(主:32570(:Gtk警告**:17:41:09.237:找不到信号处理程序"click"。你用-rdynamic编译了吗?

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

在这个网站上,我发现了这个";在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在应用程序的符号表中查找来处理,那么我的应用程序符号表有什么问题,信号无法自动连接?

我不得不自己编译你的源代码,但你的程序中似乎混合了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, "Привет, Хабр!");
}
}

最新更新