From ace28857b70d8a8fe97cdf29f937614eb13de781 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Tue, 17 May 2016 22:11:17 +0200 Subject: Enable g-ir-scanner to scan ScintillaObject signals Currently, the ScintillaObject signals can't be used from python code via gobject-introspection. This is because g-ir-scanner does not properly scan the signals. For signals, there is the additional requirement that parameters have are registered GTypes. For the sci-notify signal, this can be accomplished by boxing SCNotification. In addition, g-ir-scanner also runs on Scintilla.h where it picks up additional structs. test/gi/ is updated accordingly. The test python script is enhanced to showcase the signals (some fixes to the makefile are included as well). --- gtk/ScintillaGTK.cxx | 35 +++++-- gtk/scintilla-marshal.c | 65 +++++++++--- gtk/scintilla-marshal.h | 25 +++-- gtk/scintilla-marshal.list | 3 +- include/Scintilla.h | 9 +- include/ScintillaWidget.h | 8 +- test/gi/Scintilla-0.1.gir.good | 219 +++++++++++++++++++++++++++++++++++++++-- test/gi/filter-scintilla-h.py | 19 ++++ test/gi/gi-test.py | 9 ++ test/gi/makefile | 20 ++-- 10 files changed, 364 insertions(+), 48 deletions(-) create mode 100644 test/gi/filter-scintilla-h.py diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx index 9fc8e4cc4..f9adbc9ce 100644 --- a/gtk/ScintillaGTK.cxx +++ b/gtk/ScintillaGTK.cxx @@ -3162,9 +3162,6 @@ void ScintillaGTK::ClassInit(OBJECT_CLASS* object_class, GtkWidgetClass *widget_ container_class->forall = MainForAll; } -#define SIG_MARSHAL scintilla_marshal_NONE__INT_POINTER -#define MARSHAL_ARGUMENTS G_TYPE_INT, G_TYPE_POINTER - static void scintilla_class_init(ScintillaClass *klass) { try { OBJECT_CLASS *object_class = (OBJECT_CLASS*) klass; @@ -3179,20 +3176,20 @@ static void scintilla_class_init(ScintillaClass *klass) { G_STRUCT_OFFSET(ScintillaClass, command), NULL, //(GSignalAccumulator) NULL, //(gpointer) - SIG_MARSHAL, + scintilla_marshal_VOID__INT_OBJECT, G_TYPE_NONE, - 2, MARSHAL_ARGUMENTS); + 2, G_TYPE_INT, GTK_TYPE_WIDGET); scintilla_signals[NOTIFY_SIGNAL] = g_signal_new( SCINTILLA_NOTIFY, G_TYPE_FROM_CLASS(object_class), sigflags, G_STRUCT_OFFSET(ScintillaClass, notify), - NULL, - NULL, - SIG_MARSHAL, + NULL, //(GSignalAccumulator) + NULL, //(gpointer) + scintilla_marshal_VOID__INT_BOXED, G_TYPE_NONE, - 2, MARSHAL_ARGUMENTS); + 2, G_TYPE_INT, SCINTILLA_TYPE_NOTIFICATION); klass->command = NULL; klass->notify = NULL; @@ -3233,3 +3230,23 @@ void scintilla_release_resources(void) { } catch (...) { } } + +/* Define a dummy boxed type because g-ir-scanner is unable to + * recognize gpointer-derived types. Note that SCNotificaiton + * is always allocated on stack so copying is not appropriate. */ +static void *copy_(void *src) { return src; } +static void free_(void *doc) { } + +GType scnotification_get_type(void) +{ + static gsize type_id = 0; + if (g_once_init_enter (&type_id)) + { + gsize id = (gsize) g_boxed_type_register_static( + g_intern_static_string ("SCNotification"), + (GBoxedCopyFunc) copy_, + (GBoxedFreeFunc) free_); + g_once_init_leave(&type_id, id); + } + return (GType) type_id; +} diff --git a/gtk/scintilla-marshal.c b/gtk/scintilla-marshal.c index 5470a5ba5..c91bd0bcd 100644 --- a/gtk/scintilla-marshal.c +++ b/gtk/scintilla-marshal.c @@ -49,20 +49,20 @@ #endif /* !G_ENABLE_DEBUG */ -/* NONE:INT,POINTER (scintilla-marshal.list:1) */ +/* NONE:INT,OBJECT (scintilla-marshal.list:1) */ void -scintilla_marshal_VOID__INT_POINTER (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) +scintilla_marshal_VOID__INT_OBJECT (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) { - typedef void (*GMarshalFunc_VOID__INT_POINTER) (gpointer data1, - gint arg_1, - gpointer arg_2, - gpointer data2); - GMarshalFunc_VOID__INT_POINTER callback; + typedef void (*GMarshalFunc_VOID__INT_OBJECT) (gpointer data1, + gint arg_1, + gpointer arg_2, + gpointer data2); + GMarshalFunc_VOID__INT_OBJECT callback; GCClosure *cc = (GCClosure*) closure; gpointer data1, data2; @@ -78,11 +78,48 @@ scintilla_marshal_VOID__INT_POINTER (GClosure *closure, data1 = g_value_peek_pointer (param_values + 0); data2 = closure->data; } - callback = (GMarshalFunc_VOID__INT_POINTER) (marshal_data ? marshal_data : cc->callback); + callback = (GMarshalFunc_VOID__INT_OBJECT) (marshal_data ? marshal_data : cc->callback); callback (data1, g_marshal_value_peek_int (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), + g_marshal_value_peek_object (param_values + 2), + data2); +} + +/* NONE:INT,BOXED (scintilla-marshal.list:2) */ +void +scintilla_marshal_VOID__INT_BOXED (GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__INT_BOXED) (gpointer data1, + gint arg_1, + gpointer arg_2, + gpointer data2); + GMarshalFunc_VOID__INT_BOXED callback; + GCClosure *cc = (GCClosure*) closure; + gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__INT_BOXED) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_int (param_values + 1), + g_marshal_value_peek_boxed (param_values + 2), data2); } diff --git a/gtk/scintilla-marshal.h b/gtk/scintilla-marshal.h index 9116a56c9..7d5e17bba 100644 --- a/gtk/scintilla-marshal.h +++ b/gtk/scintilla-marshal.h @@ -6,14 +6,23 @@ G_BEGIN_DECLS -/* NONE:INT,POINTER (scintilla-marshal.list:1) */ -extern void scintilla_marshal_VOID__INT_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); -#define scintilla_marshal_NONE__INT_POINTER scintilla_marshal_VOID__INT_POINTER +/* NONE:INT,OBJECT (scintilla-marshal.list:1) */ +extern void scintilla_marshal_VOID__INT_OBJECT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +#define scintilla_marshal_NONE__INT_OBJECT scintilla_marshal_VOID__INT_OBJECT + +/* NONE:INT,BOXED (scintilla-marshal.list:2) */ +extern void scintilla_marshal_VOID__INT_BOXED (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); +#define scintilla_marshal_NONE__INT_BOXED scintilla_marshal_VOID__INT_BOXED G_END_DECLS diff --git a/gtk/scintilla-marshal.list b/gtk/scintilla-marshal.list index e5750ecb6..ddc8ae87e 100644 --- a/gtk/scintilla-marshal.list +++ b/gtk/scintilla-marshal.list @@ -1 +1,2 @@ -NONE:INT,POINTER +NONE:INT,OBJECT +NONE:INT,BOXED diff --git a/include/Scintilla.h b/include/Scintilla.h index c985cea77..99bc6e7b1 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -1121,6 +1121,13 @@ struct Sci_RangeToFormat { #define RangeToFormat Sci_RangeToFormat +#ifndef __cplusplus +/* For the GTK+ platform, g-ir-scanner needs to have these typedefs. This + * is not required in C++ code and actually seems to break ScintillaEditPy */ +typedef struct Sci_NotifyHeader Sci_NotifyHeader; +typedef struct SCNotification SCNotification; +#endif + struct Sci_NotifyHeader { /* Compatible with Windows NMHDR. * hwndFrom is really an environment specific window handle or pointer @@ -1133,7 +1140,7 @@ struct Sci_NotifyHeader { #define NotifyHeader Sci_NotifyHeader struct SCNotification { - struct Sci_NotifyHeader nmhdr; + Sci_NotifyHeader nmhdr; Sci_Position position; /* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */ /* SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, SCN_CALLTIPCLICK, */ diff --git a/include/ScintillaWidget.h b/include/ScintillaWidget.h index f4ae18208..1721f65d9 100644 --- a/include/ScintillaWidget.h +++ b/include/ScintillaWidget.h @@ -38,14 +38,18 @@ struct _ScintillaObject { struct _ScintillaClass { GtkContainerClass parent_class; - void (* command) (ScintillaObject *ttt); - void (* notify) (ScintillaObject *ttt); + void (* command) (ScintillaObject *sci, int cmd, GtkWidget *window); + void (* notify) (ScintillaObject *sci, int id, SCNotification *scn); }; GType scintilla_object_get_type (void); GtkWidget* scintilla_object_new (void); gintptr scintilla_object_send_message (ScintillaObject *sci, unsigned int iMessage, guintptr wParam, gintptr lParam); + +GType scnotification_get_type (void); +#define SCINTILLA_TYPE_NOTIFICATION (scnotification_get_type()) + #ifndef G_IR_SCANNING /* The legacy names confuse the g-ir-scanner program */ typedef struct _ScintillaClass ScintillaClass; diff --git a/test/gi/Scintilla-0.1.gir.good b/test/gi/Scintilla-0.1.gir.good index b3919a725..771edae6e 100644 --- a/test/gi/Scintilla-0.1.gir.good +++ b/test/gi/Scintilla-0.1.gir.good @@ -14,6 +14,24 @@ and/or use gtk-doc annotations. --> shared-library="libscintilla.so" c:identifier-prefixes="Scintilla" c:symbol-prefixes="scintilla"> + + + + + + + + + + + + + + + + + + @@ -36,9 +54,15 @@ and/or use gtk-doc annotations. --> - + + + + + + + @@ -46,9 +70,15 @@ and/or use gtk-doc annotations. --> - + + + + + + + @@ -85,7 +115,7 @@ and/or use gtk-doc annotations. --> - + @@ -98,7 +128,7 @@ and/or use gtk-doc annotations. --> - + @@ -115,9 +145,15 @@ and/or use gtk-doc annotations. --> - + + + + + + + @@ -127,12 +163,183 @@ and/or use gtk-doc annotations. --> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/gi/filter-scintilla-h.py b/test/gi/filter-scintilla-h.py new file mode 100644 index 000000000..0743f9ef2 --- /dev/null +++ b/test/gi/filter-scintilla-h.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# Filters Scintilla.h to not contain generated stuff or deprecated defines + +import sys +import fileinput + +def main(): + inhibit = 0 + for line in fileinput.input(): + if line.startswith("/* ++Autogenerated") or line.startswith("#ifdef INCLUDE_DEPRECATED_FEATURES"): + inhibit += 1 + if inhibit == 0: + sys.stdout.write(line) + if line.startswith("/* --Autogenerated") or line.startswith("#endif"): + if (inhibit > 0): + inhibit -= 1 + +if __name__ == "__main__": + main() diff --git a/test/gi/gi-test.py b/test/gi/gi-test.py index 6c775ea0c..b047ecec9 100644 --- a/test/gi/gi-test.py +++ b/test/gi/gi-test.py @@ -8,9 +8,18 @@ gi.require_version('Scintilla', '0.1') from gi.repository import Scintilla from gi.repository import Gtk +def on_notify(sci, id, scn): + if (scn.nmhdr.code == 2001): # SCN_CHARADDED + print ("sci-notify: id: %d, char added: %d" % (id, scn.ch)) + elif (scn.nmhdr.code == 2008): # SCN_MODIFIED + print ("sci-notify: id: %d, pos: %d, mod type: %d" % (id, scn.position, scn.modificationType)) + else: + print ("sci-notify: id: %d, scn.nmhdr.code: %d" % (id, scn.nmhdr.code)) + win = Gtk.Window() win.connect("delete-event", Gtk.main_quit) sci = Scintilla.Object() +sci.connect("sci-notify", on_notify) win.add(sci) win.show_all() win.resize(400,300) diff --git a/test/gi/makefile b/test/gi/makefile index cf7522303..8b01de341 100644 --- a/test/gi/makefile +++ b/test/gi/makefile @@ -12,20 +12,26 @@ GTK_LIBS = $(shell pkg-config --libs gtk+-$(GTKVERSION)) GTK_CFLAGS = $(shell pkg-config --cflags gtk+-$(GTKVERSION)) PWD = $(shell pwd) -FORCE: +.PHONY: test clean FORCE ../../bin/scintilla.a: FORCE $(MAKE) -C ../../gtk all +Scintilla-filtered.h: ../../include/Scintilla.h + python filter-scintilla-h.py $< > $@ + libscintilla.so: ../../bin/scintilla.a $(CXX) -shared -o $@ -Wl,--whole-archive $^ -Wl,--no-whole-archive $(GTK_LIBS) -Scintilla-0.1.gir: libscintilla.so +Scintilla-0.1.gir: libscintilla.so Scintilla-filtered.h LDFLAGS=-Wl,-rpath=$(shell pwd) \ - $(GI_SCANNER) --warn-all -i Gtk-$(GTKVERSION) -DG_IR_SCANNING -DGTK \ - --cflags-begin $(GTK_CFLAGS) -include gtk/gtk.h --cflags-end \ + $(GI_SCANNER) --no-libtool --warn-all -i Gtk-$(GTKVERSION) -DG_IR_SCANNING -DGTK \ + --cflags-begin $(GTK_CFLAGS) -include gtk/gtk.h \ + -include Scintilla-filtered.h -I../../include --cflags-end \ + --accept-unprefixed \ --c-include Scintilla.h --c-include ScintillaWidget.h \ - -n Scintilla --nsversion 0.1 --library scintilla -L$(PWD) ../../include/ScintillaWidget.h \ + -n Scintilla --nsversion 0.1 --library scintilla -L$(PWD) \ + ../../include/Sci_Position.h ../../include/ScintillaWidget.h Scintilla-filtered.h \ -o $@ Scintilla-0.1.typelib: Scintilla-0.1.gir @@ -35,9 +41,9 @@ clean: rm -f libscintilla.so Scintilla-0.1.gir Scintilla-0.1.typelib $(MAKE) -C ../../gtk clean -test: Scintilla-0.1.gir +test: Scintilla-0.1.gir Scintilla-0.1.typelib @echo Verifying Scintilla-0.1.gir file - @diff $^.good $^ || (echo "GIR FILE MISMATCH!"; exit 1) + @diff $<.good $< || (echo "GIR FILE MISMATCH!"; exit 1) @echo Launching gi-test.py python program GI_TYPELIB_PATH=$(PWD) LD_LIBRARY_PATH=$(PWD) \ python $(PWD)/gi-test.py -- cgit v1.2.3