Skip to content

Instantly share code, notes, and snippets.

@caiorss
Last active June 24, 2020 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save caiorss/d81dd9c422dc93ad4104b5e79259afdf to your computer and use it in GitHub Desktop.
Save caiorss/d81dd9c422dc93ad4104b5e79259afdf to your computer and use it in GitHub Desktop.
Gtk with dynamic loading
cmake_minimum_required(VERSION 3.9)
project(gtk-sample)
#========== Global Configurations =============#
#----------------------------------------------#
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_VERBOSE_MAKEFILE ON)
add_executable( gtk-dlopen gtk-dlopen.cpp)
target_link_libraries( gtk-dlopen dl )
#include <iostream>
#include <cstring>
#include <cassert>
// Uses: dlopen(), dlclose(), ...
#include <dlfcn.h>
// ---- Copied from GTK headers ------//
typedef char gchar;
typedef short gshort;
typedef long glong;
typedef int gint;
typedef gint gboolean;
typedef unsigned char guchar;
typedef unsigned short gushort;
typedef unsigned long gulong;
typedef unsigned int guint;
typedef float gfloat;
typedef double gdouble;
typedef void* gpointer;
typedef const void* gconstpointer;
enum class GtkWindowType
{
GTK_WINDOW_TOPLEVEL,
GTK_WINDOW_POPUP
};
enum class GConnectFlags
{
G_CONNECT_AFTER = 1 << 0,
G_CONNECT_SWAPPED = 1 << 1
};
template<typename TFun>
TFun load_symbol(void* hnd, std::string symbol)
{
void* hSym = dlsym(hnd, symbol.c_str());
if(hSym == nullptr)
{
std::string msg = std::string(" [Error] symbol not found: ") + symbol;
throw std::runtime_error(msg);
}
return reinterpret_cast<TFun>(hSym);
}
// Opaque type (aka incomplete type)
struct GClosure;
// -------- Function Pointers type aliases -------------------//
using GCallback = void (*) (void);
using GClosureNotify = void (*) (gpointer data, GClosure* closure);
using g_signal_connect_data_t = gulong (*) ( gpointer instance
, const gchar* detailed_signal
, GCallback c_handler
, gpointer data
, GClosureNotify destroy_data
, GConnectFlags connect_flags
);
int main(int argc, char** argv)
{
std::string shared_lib = [&]() -> std::string
{
if(argc < 2) return "libgtk-3.so.0";
return argv[1];
}();
std::cout << " [INFO] Loading shared library: " << shared_lib << "\n";
// void *dlopen(const char *filename, int flags);
// Handle to shared library
void* hnd = dlopen(shared_lib.c_str(), RTLD_NOW | RTLD_GLOBAL);
if(hnd == nullptr){ fprintf(stderr, "%s\n", dlerror()); }
assert( hnd != nullptr );
void* hSym = nullptr;
// --------- Load gtk_init_check function pointer ------- //
hSym = dlsym(hnd, "gtk_init_check");
assert(hSym != nullptr);
using gtk_init_check_t = gboolean (*) (int* argc, char*** argv);
auto gtk_init_check = reinterpret_cast<gtk_init_check_t>(hSym);
// ------- Load remaining function pointers (symbols) --------//
//-----------------------------------------------------------//
// opaque pointer
struct GtkWidget;
using gkt_window_new_t = GtkWidget* (*) (int);
auto gtk_window_new = load_symbol<gkt_window_new_t>(hnd, "gtk_window_new");
auto gtk_widget_show = load_symbol<void (*) (GtkWidget*)>(hnd, "gtk_widget_show");
auto gtk_main = load_symbol<void (*) ()>(hnd, "gtk_main");
using gtk_window_set_title_t = void (*) (GtkWidget* window, const gchar* title);
auto gtk_window_set_title = load_symbol<gtk_window_set_title_t>(hnd, "gtk_window_set_title");
using gtk_widget_set_size_t = void (*) (GtkWidget*, gint, gint);
auto gtk_widget_set_size = load_symbol<gtk_widget_set_size_t>(hnd, "gtk_widget_set_size_request");
auto gtk_main_quit = load_symbol<void (*) ()>(hnd, "gtk_main_quit");
auto gtk_signal_connect_data
= load_symbol<g_signal_connect_data_t>(hnd, "g_signal_connect_data");
/** ------- Build Window GUI - Graphical User Interface ----------**/
// Call function pointer
gtk_init_check(&argc, &argv);
GtkWidget* window = gtk_window_new( (int) GtkWindowType::GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size(window, 400, 500);
gtk_window_set_title(window, "My GTK Window");
gtk_widget_show(window);
gtk_signal_connect_data( window // Widget
, "destroy" // Event name
, gtk_main_quit // Callback
, nullptr // Pointer to data (closure )
, nullptr
, (GConnectFlags) 0 // GConnect flags
);
std::cout << " [INFO] Window running. OK! " << "\n";
gtk_main();
// Always close shared library handler.
dlclose(hnd);
std::cout << " [INFO] Shutdown gracefully. Ok. \n" ;
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment