Giter Site home page Giter Site logo

gtk-glade-dl's Introduction

gtk-glade-dl

Consider the following two programs, glossing over what compiler flags we need to get them running. (See the Makefile).

gtk-glade-dl/demo.cpp

Lines 1 to 27 in c53be75

#include <gtkmm.h>
extern "C"
void on_quit_btn_clicked(){
Gtk::Main::quit();
}
Glib::RefPtr<Gtk::Builder> builder;
extern "C"
void on_app_activate(int argc, char** argv, char* gmodule){
Gtk::Main app = Gtk::Main(argc, argv, false);
builder = Gtk::Builder::create();
builder->add_from_file("demo.ui");
gtk_builder_connect_signals(builder->gobj(), NULL);
Gtk::Window* main_win;
builder->get_widget<Gtk::Window>("main_win", main_win);
app.run(*main_win);
}
int main(int argc, char** argv ) {
on_app_activate(argc, argv, NULL);
}

gtk-glade-dl/dl.c

Lines 6 to 19 in c53be75

typedef void (*activate_t)(int, char**);
int main(int argc, char** argv) {
activate_t activate;
char* gmodule = "./demo.so";
void* handle = dlopen(gmodule, RTLD_NOW);
if (!handle) {
printf("%s\n", dlerror());
return 1;
}
activate = (activate_t) dlsym(handle, "on_app_activate");
activate(argc, argv);
return 0;
}

On their face, the programs should have the same behaviour: both the entry point of demo and dl call on_app_activate. What we expect to happen is a window to open, containing a button we can click to quit the program. demo works as expected. On running dl, however, we are faced with a warning from Gtk

(dl:2875124): Gtk-WARNING **: 14:19:58.729: Could not find signal handler 'on_quit_btn_clicked'

and indeed clicking the button has no effect.

On the internet, many people have had issues compiling and linking against Gtk+. We have to use the right compiler flags (from pkg-config and -rdynamic -export-dynamic). We have to flag the callback with extern "C" to avoid name mangling. The issue here is not one of these.

To understand what's wrong, let's look the documentation for gtk_builder_connect_signals:

This method is a simpler variation of gtk_builder_connect_signals_full(). It uses GModule's introspective features (by opening the module NULL) to look at the application's symbol table. From here it tries to match the signal handler names given in the interface description with symbols in the application and connects the signals.

The issue is that when called from dl, GModule tries to find on_quit_btn_clicked in the symbol table of dl. But on_quit_button_clicked is in demo.so, and we have to tell GModule to look there. Can we do that? The source for gtk_builder_connect_signals() contains these important lines

  args = g_slice_new0 (connect_args);
  args->module = g_module_open (NULL, G_MODULE_BIND_LAZY);
  args->data = user_data;
  
  gtk_builder_connect_signals_full (builder,
                                    gtk_builder_connect_signals_default,
                                    args);

It looks like we just need to change out the NULL in the call to g_module_open. The documentation tells us we can just pass the file name as a C string.

We change the signature of on_app_activate so that we can pass in argument that tells us if we're in the main program, or being dynamically loaded. If this argument is a char* it can be NULL in the former case and double as the name of the .so in the latter.

gtk-glade-dl/demo.cpp

Lines 40 to 51 in 0f5df9b

void on_app_activate(int argc, char** argv, char* gmodule){
Gtk::Main app = Gtk::Main(argc, argv, false);
builder = Gtk::Builder::create();
builder->add_from_file("demo.ui");
connect_args* args;
args = g_slice_new0 (connect_args);
args->gmodule = g_module_open (gmodule, G_MODULE_BIND_LAZY);
args->data = NULL;
gtk_builder_connect_signals_full (builder->gobj(),
gtk_builder_connect_signals_default,
args);
Now, gtk_builder_connect_signals_default is not exported in gtkbuilder.h, so we have to provide the implementation, i.e. copy-paste from source.

gtk-glade-dl/demo.cpp

Lines 15 to 16 in 0f5df9b

static void
gtk_builder_connect_signals_default (GtkBuilder *builder,

All that remains now is modifying dl.c to account for the new signature.

typedef void (*activate_t)(int, char**, char*);
activate(argc, argv, gmodule);

After recompiling, dl now works: clicking the quit button does, in fact, quit.

Instead of passing the filename as a string, we can deduce it through introspection. With the backtrace() and backtrace_symbols() functions from execinfo.h (see backtrace(3) man page), we can obtain backtraces that look something like

./demo.so(on_app_activate+0x202) [0x7fc6c66c1752]

The first stack frame from backtrace() must be in the file containing on_app_activate. We can then just cut out the file name, and pass that to gmodule

gtk-glade-dl/demo.cpp

Lines 45 to 50 in 0e73a2d

void* trace[1];
int trace_l = backtrace(trace, 1);
bt_symbols = backtrace_symbols(trace, trace_l);
*strchr(bt_symbols[0], '(') = '\0';
gmodule = bt_symbols[0];
printf("Looking up symbols in %s.\n", gmodule);
(Of course, we should really use something more sophisticated, like a regular expression, for this in case the file name could contain (.)

For some reason that I do not understand, when loading dynamically the leading ./ must be present; but when running as the main program, it must be absent. Therefore the third argument to on_app_activate is not dropped, but changed to a flag

gtk-glade-dl/demo.cpp

Lines 41 to 44 in 0e73a2d

void on_app_activate(int argc, char** argv, int dynamic){
char* gmodule = NULL;
char** bt_symbols = NULL;
if (dynamic) {
so that we can still pass NULL if running as the main program.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.