summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Hergert <chergert@redhat.com>2022-12-22 13:11:11 -0800
committerChristian Hergert <chergert@redhat.com>2022-12-22 13:11:39 -0800
commit441ccc244c068124ea687f379fe6935e46fcdd2b (patch)
treea6d59d0d9f5a7eb3c8ee2eda7615c4f42f7d9b7b
parent5ac516291a500f9409f53282bc781e961fe98b44 (diff)
downloadgtksourceview-441ccc244c068124ea687f379fe6935e46fcdd2b.tar.gz
init: call gtk_source_init() from library static constructor
This uses static constructors like we do in a few other GNOME libraries to initialize state up front before main() is called, or when the library is dynamically loaded via dlopen(). This allows language bindings to omit the call to GtkSource.init(). We couldn't do this in GtkSourceView 4.x and previous due to gtk_init() requiring argc/argv parameters which is no longer the case. Additionally, repeated calls to gtk_init() are ignored.
-rw-r--r--gtksourceview/gconstructor.h161
-rw-r--r--gtksourceview/gtksourceinit.c18
2 files changed, 176 insertions, 3 deletions
diff --git a/gtksourceview/gconstructor.h b/gtksourceview/gconstructor.h
new file mode 100644
index 00000000..29509e4a
--- /dev/null
+++ b/gtksourceview/gconstructor.h
@@ -0,0 +1,161 @@
+/* GLIB - Library of useful routines for C programming
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+ * file for a list of people on the GLib Team. See the ChangeLog
+ * files for a list of changes. These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#ifndef __G_CONSTRUCTOR_H__
+#define __G_CONSTRUCTOR_H__
+
+/*
+ If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and
+ destructors, in a usable way, including e.g. on library unload. If not you're on
+ your own.
+
+ Some compilers need #pragma to handle this, which does not work with macros,
+ so the way you need to use this is (for constructors):
+
+ #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA
+ #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor)
+ #endif
+ G_DEFINE_CONSTRUCTOR(my_constructor)
+ static void my_constructor(void) {
+ ...
+ }
+
+*/
+
+#ifndef __GTK_DOC_IGNORE__
+
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void);
+#define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void);
+
+#elif defined (_MSC_VER) && (_MSC_VER >= 1500)
+/* Visual studio 2008 and later has _Pragma */
+
+/*
+ * Only try to include gslist.h if not already included via glib.h,
+ * so that items using gconstructor.h outside of GLib (such as
+ * GResources) continue to build properly.
+ */
+#ifndef __G_LIB_H__
+#include "gslist.h"
+#endif
+
+#include <stdlib.h>
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* We do some weird things to avoid the constructors being optimized
+ * away on VS2015 if WholeProgramOptimization is enabled. First we
+ * make a reference to the array from the wrapper to make sure its
+ * references. Then we use a pragma to make sure the wrapper function
+ * symbol is always included at the link stage. Also, the symbols
+ * need to be extern (but not dllexport), even though they are not
+ * really used from another object file.
+ */
+
+/* We need to account for differences between the mangling of symbols
+ * for x86 and x64/ARM/ARM64 programs, as symbols on x86 are prefixed
+ * with an underscore but symbols on x64/ARM/ARM64 are not.
+ */
+#ifdef _M_IX86
+#define G_MSVC_SYMBOL_PREFIX "_"
+#else
+#define G_MSVC_SYMBOL_PREFIX ""
+#endif
+
+#define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX)
+#define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX)
+
+#define G_MSVC_CTOR(_func,_sym_prefix) \
+ static void _func(void); \
+ extern int (* _array ## _func)(void); \
+ int _func ## _wrapper(void) { _func(); g_slist_find (NULL, _array ## _func); return 0; } \
+ __pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \
+ __pragma(section(".CRT$XCU",read)) \
+ __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper;
+
+#define G_MSVC_DTOR(_func,_sym_prefix) \
+ static void _func(void); \
+ extern int (* _array ## _func)(void); \
+ int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL, _array ## _func); return 0; } \
+ __pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \
+ __pragma(section(".CRT$XCU",read)) \
+ __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined (_MSC_VER)
+
+#define G_HAS_CONSTRUCTORS 1
+
+/* Pre Visual studio 2008 must use #pragma section */
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+ section(".CRT$XCU",read)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+ static void _func(void); \
+ static int _func ## _wrapper(void) { _func(); return 0; } \
+ __declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper;
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+ section(".CRT$XCU",read)
+#define G_DEFINE_DESTRUCTOR(_func) \
+ static void _func(void); \
+ static int _func ## _constructor(void) { atexit (_func); return 0; } \
+ __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor;
+
+#elif defined(__SUNPRO_C)
+
+/* This is not tested, but i believe it should work, based on:
+ * http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c
+ */
+
+#define G_HAS_CONSTRUCTORS 1
+
+#define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1
+#define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1
+
+#define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \
+ init(_func)
+#define G_DEFINE_CONSTRUCTOR(_func) \
+ static void _func(void);
+
+#define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \
+ fini(_func)
+#define G_DEFINE_DESTRUCTOR(_func) \
+ static void _func(void);
+
+#else
+
+/* constructors not supported for this compiler */
+
+#endif
+
+#endif /* __GTK_DOC_IGNORE__ */
+#endif /* __G_CONSTRUCTOR_H__ */
diff --git a/gtksourceview/gtksourceinit.c b/gtksourceview/gtksourceinit.c
index 9f5cb6b7..a883b8fb 100644
--- a/gtksourceview/gtksourceinit.c
+++ b/gtksourceview/gtksourceinit.c
@@ -23,6 +23,8 @@
#include <glib/gi18n-lib.h>
+#include "gconstructor.h"
+
#include "gtksourcebuffer.h"
#include "gtksourcebufferinputstream-private.h"
#include "gtksourcebufferoutputstream-private.h"
@@ -164,9 +166,9 @@ get_locale_dir (void)
void
gtk_source_init (void)
{
- static gboolean done = FALSE;
+ static gsize initialized;
- if (!done)
+ if (g_once_init_enter (&initialized))
{
GdkDisplay *display;
gchar *locale_dir;
@@ -177,6 +179,8 @@ gtk_source_init (void)
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ gtk_init ();
+
/* Due to potential deadlocks when registering types, we need to
* ensure the dependent private class GtkSourceBufferOutputStream
* and GtkSourceBufferInputStream have been registered up front.
@@ -240,10 +244,18 @@ gtk_source_init (void)
gtk_icon_theme_add_search_path (icon_theme, HICOLORDIR);
}
- done = TRUE;
+ g_once_init_leave (&initialized, TRUE);
}
}
+G_DEFINE_CONSTRUCTOR (_gtk_source_init_ctor)
+
+static void
+_gtk_source_init_ctor (void)
+{
+ gtk_source_init ();
+}
+
/**
* gtk_source_finalize:
*