Skip to content

Commit bdf7461

Browse files
committed
make GLib-derived types static across modules
1 parent dcdb768 commit bdf7461

File tree

2 files changed

+41
-17
lines changed

2 files changed

+41
-17
lines changed

src/GLib/gtype.jl

+32-17
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const fundamental_types = (
3838
#(:GVariant, Ptr{GVariant}, GVariant, :variant),
3939
)
4040
# NOTE: in general do not cache ids, except for the fundamental values
41-
g_type_from_name(name::Symbol) = ccall((:g_type_from_name,libgobject),Int,(Ptr{Uint8},),name)
41+
g_type_from_name(name::Symbol) = ccall((:g_type_from_name,libgobject),GType,(Ptr{Uint8},),name)
4242
# these constants are used elsewhere
4343
const gvoid_id = g_type_from_name(:void)
4444
const gboxed_id = g_type_from_name(:GBoxed)
@@ -62,6 +62,7 @@ type GObjectAny <: GObjectI
6262
handle::Ptr{GObject}
6363
GObjectAny(handle::Ptr{GObject}) = (handle != C_NULL ? gc_ref(new(handle)) : error("Cannot construct $gname with a NULL pointer"))
6464
end
65+
g_type(obj::GObjectI) = g_type(typeof(obj))
6566
g_type(::Type{GObjectI}) = gobject_id
6667
g_type(::Type{GObject}) = gobject_id
6768
g_type(::Type{GObjectAny}) = gobject_id
@@ -77,34 +78,43 @@ function g_type(name::Symbol, lib, symname::Symbol)
7778
return g_type(gtype_wrappers[name])
7879
end
7980
if !isa(lib,String)
80-
lib = eval(current_module(),lib)
81+
lib = eval(current_module(), lib)
8182
end
8283
libptr = dlopen(lib)
8384
fnptr = dlsym(libptr, string(symname,"_get_type"))
8485
typ = ccall(fnptr, GType, ())
8586
dlclose(libptr)
8687
typ
8788
end
89+
g_type(name::Symbol, lib, symname::Expr) = eval(current_module(), symname)
8890

8991
function get_iface_decl(name::Symbol, iname::Symbol, gtyp::GType)
90-
if name in keys(gtype_ifaces)
92+
if isdefined(current_module(), iname)
9193
return nothing
9294
end
95+
if name === :GObject
96+
return :( const $(esc(iname)) = gtype_ifaces[:GObject] )
97+
end
9398
parent = g_type_parent(gtyp)
9499
@assert parent != 0
95100
pname = g_type_name(parent)
96101
piname = symbol(string(pname,'I'))
97102
piface_decl = get_iface_decl(pname, piname, parent)
98103
quote
99-
$piface_decl
100-
abstract $(esc(iname)) <: $(esc(piname))
101-
gtype_ifaces[$(Meta.quot(name))] = $(esc(iname))
104+
if $(Meta.quot(iname)) in keys(gtype_ifaces)
105+
const $(esc(iname)) = gtype_ifaces[$(Meta.quot(name))]
106+
else
107+
$piface_decl
108+
abstract $(esc(iname)) <: $(esc(piname))
109+
gtype_ifaces[$(Meta.quot(name))] = $(esc(iname))
110+
end
102111
end
103112
end
104113

114+
get_gtype_decl(name::Symbol, lib, symname::Expr) = esc(symname)
105115
function get_gtype_decl(name::Symbol, lib, symname::Symbol)
106116
quote
107-
GLib.g_type(::Type{$(esc(name))}) = ccall(($(symbol(string(symname,"_get_type"))), $(esc(lib))), GType, ())
117+
GLib.g_type(::Type{$(esc(name))}) = ccall(($(Meta.quot(symbol(string(symname,"_get_type")))), $(esc(lib))), GType, ())
108118
end
109119
end
110120

@@ -116,12 +126,17 @@ macro Gtype(name,lib,symname)
116126
end
117127
iname = symbol(string(name,'I'))
118128
quote
119-
$(get_iface_decl(name, iname, gtyp))
120-
type $(esc(name)) <: $(esc(iname))
121-
handle::Ptr{GObjectI}
122-
$(esc(name))(handle::Ptr{GObjectI}) = (handle != C_NULL ? gc_ref(new(handle)) : error($("Cannot construct $name with a NULL pointer")))
129+
if $(Meta.quot(name)) in keys(gtype_wrappers)
130+
const $(esc(iname)) = gtype_ifaces[$(Meta.quot(name))]
131+
const $(esc(name)) = gtype_wrappers[$(Meta.quot(name))]
132+
else
133+
$(get_iface_decl(name, iname, gtyp))
134+
type $(esc(name)) <: $(esc(iname))
135+
handle::Ptr{GObjectI}
136+
$(esc(name))(handle::Ptr{GObjectI}) = (handle != C_NULL ? gc_ref(new(handle)) : error($("Cannot construct $name with a NULL pointer")))
137+
end
138+
gtype_wrappers[$(Meta.quot(name))] = $(esc(name))
123139
end
124-
gtype_wrappers[$(Meta.quot(name))] = $(esc(name))
125140
$(get_gtype_decl(name, lib, symname))
126141
end
127142
end
@@ -143,8 +158,8 @@ macro quark_str(q)
143158
end
144159
const jlref_quark = quark"julia_ref"
145160

146-
# All GtkWidgets are expected to have a 'handle' field
147-
# of type Ptr{GObjectI} corresponding to the Gtk object
161+
# All GObjects are expected to have a 'handle' field
162+
# of type Ptr{GObjectI} corresponding to the GLib object
148163
convert(::Type{Ptr{GObjectI}},w::GObjectI) = w.handle
149164
convert{T<:GObjectI}(::Type{T},w::Ptr{T}) = convert(T,convert(Ptr{GObjectI},w))
150165
eltype{T<:GObjectI}(::GSList{T}) = T
@@ -237,16 +252,16 @@ end
237252

238253
function gc_unref_weak(x::GObjectI)
239254
# this strongly destroys and invalidates the object
240-
# it is intended to be called by Gtk, not in user code function
241-
# note: this may be called multiple times by Gtk
255+
# it is intended to be called by GLib, not in user code function
256+
# note: this may be called multiple times by GLib
242257
x.handle = C_NULL
243258
global gc_preserve_gtk
244259
delete!(gc_preserve_gtk, x)
245260
nothing
246261
end
247262
function gc_unref(x::GObjectI)
248263
# this strongly destroys and invalidates the object
249-
# it is intended to be called by Gtk, not in user code function
264+
# it is intended to be called by GLib, not in user code function
250265
ref = ccall((:g_object_get_qdata,libgobject),Ptr{Void},(Ptr{GObjectI},Uint32),x,jlref_quark)
251266
if ref != C_NULL && x !== unsafe_pointer_to_objref(ref)
252267
# We got called because we are no longer the default object for this handle, but we are still alive

test/glib_tests.jl

+9
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,12 @@ wrap2 = convert(GObject, hnd)
1212
@assert wrap == wrap2
1313

1414
print(wrap,'\n') #should display properties
15+
16+
module Test
17+
import Gtk
18+
using Gtk.GLib
19+
@Gtype GtkWidget Gtk.libgtk gtk_widget
20+
end
21+
22+
@assert Test.GtkWidget == Gtk.GtkWidget
23+
@assert Test.GtkWidgetI == Gtk.GtkWidgetI

0 commit comments

Comments
 (0)