Skip to content

Commit 0a8b481

Browse files
committed
allow creating a GValue containing a GType (typically translated from a Julia type)
1 parent c70001c commit 0a8b481

File tree

7 files changed

+72
-59
lines changed

7 files changed

+72
-59
lines changed

LICENSE.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
The Julia-Gtk bindings are licensed under the MIT License:
22

3-
> Copyright (c) 2013: Jameson Nash and other contributors:
3+
> Copyright (c) 2013-2014: Jameson Nash and other contributors:
44
>
55
> https://github.com/JuliaLang/Gtk.jl/contributors
66
>

src/GLib/GLib.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module GLib
22
import Base: convert, show, showall, showcompact, size, length, getindex, setindex!,
33
start, next, done, eltype
44
export GObject, GObjectI, GType, @Gtype, @Gabstract
5-
export Enum, GError, GValue, gvalue, make_gvalue
5+
export Enum, GError, GValue, gvalue, make_gvalue, g_type
66
export GSList, gslist, gslist2, gc_ref, gc_unref, gc_ref_closure
77
export signal_connect, signal_emit, signal_handler_disconnect
88
export signal_handler_block, signal_handler_unblock

src/GLib/MutableTypes.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ Base.unsafe_store!(b::MutableA, x) = (b.x[b.i] = x)
4242
Base.getindex(b::MutableX) = b.x
4343
Base.getindex(b::MutableA) = b.x[b.i]
4444

45-
Base.setindex!(b::MutableX, x) = (b.x = x)
46-
Base.setindex!(b::MutableA, x) = (b.x[b.i] = x)
45+
Base.setindex!{T}(b::MutableX{T}, x::T) = (b.x = x)
46+
Base.setindex!{T,N}(b::MutableA{T,N}, x::T) = (b.x[b.i] = x)
4747

4848
end

src/GLib/gerror.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ convert(::Type{GError}, err::Ptr{GError}) = GError(err)
99
GError(err::Ptr{GError}) = unsafe_load(err)
1010
function GError(f::Function)
1111
err = mutable(Ptr{GError})
12-
err[] = C_NULL
12+
err.x = C_NULL
1313
if !f(err) || err[] != C_NULL
1414
gerror = GError(err[])
1515
emsg = bytestring(gerror.message)

src/GLib/gtype.jl

+13-9
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,23 @@ const fundamental_types = (
3434
(:GBoxed, Ptr{Void}, None, :boxed),
3535
(:GParam, Ptr{GParamSpec}, Ptr{GParamSpec},:param),
3636
(:GObject, Ptr{GObject}, GObject, :object),
37-
#(:GType, Int, None, :gtype), # this isn't a fundamental type
3837
#(:GVariant, Ptr{GVariant}, GVariant, :variant),
3938
)
40-
# NOTE: in general do not cache ids, except for the fundamental values
39+
# NOTE: in general do not cache ids, except for these fundamental values
4140
g_type_from_name(name::Symbol) = ccall((:g_type_from_name,libgobject),GType,(Ptr{Uint8},),name)
42-
# these constants are used elsewhere
43-
const gvoid_id = g_type_from_name(:void)
41+
const fundamental_ids = tuple(Int[g_type_from_name(name) for (name,c,j,f) in fundamental_types]...)
42+
# this constant is needed elsewhere, but doesn't have a matching Julia type so it can't be used from g_type
4443
const gboxed_id = g_type_from_name(:GBoxed)
45-
const gobject_id = g_type_from_name(:GObject)
46-
const gstring_id = g_type_from_name(:gchararray)
44+
45+
g_type(gtyp::GType) = gtyp
46+
let jtypes = Expr(:block, :( g_type(::Type{Void}) = $(g_type_from_name(:void)) ))
47+
for (i,(name, ctype, juliatype, g_value_fn)) in enumerate(fundamental_types)
48+
if juliatype !== None
49+
push!(jtypes.args, :( g_type{T<:$juliatype}(::Type{T}) = convert(GType,$(fundamental_ids[i])) ))
50+
end
51+
end
52+
eval(jtypes)
53+
end
4754

4855
G_TYPE_FROM_CLASS(w::Ptr{Void}) = unsafe_load(convert(Ptr{GType},w))
4956
G_OBJECT_GET_CLASS(w::GObject) = G_OBJECT_GET_CLASS(w.handle)
@@ -63,9 +70,6 @@ type GObjectAny <: GObjectI
6370
GObjectAny(handle::Ptr{GObject}) = (handle != C_NULL ? gc_ref(new(handle)) : error("Cannot construct $gname with a NULL pointer"))
6471
end
6572
g_type(obj::GObjectI) = g_type(typeof(obj))
66-
g_type(::Type{GObjectI}) = gobject_id
67-
g_type(::Type{GObject}) = gobject_id
68-
g_type(::Type{GObjectAny}) = gobject_id
6973

7074
const gtype_ifaces = Dict{Symbol,Type}()
7175
const gtype_wrappers = Dict{Symbol,Type}()

src/GLib/gvalues.jl

+48-39
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ immutable GValue
66
field3::Uint64
77
GValue() = new(0,0,0)
88
end
9-
typealias GV Union(Mutable{GValue}, Vector{GValue}, Ptr{GValue})
9+
typealias GV Union(Mutable{GValue}, Ptr{GValue})
1010
Base.zero(::Type{GValue}) = GValue()
1111
function gvalue{T}(::Type{T})
1212
v = mutable(GValue())
@@ -21,16 +21,30 @@ end
2121
function gvalues(xs...)
2222
v = zeros(GValue, length(xs))
2323
for (i,x) in enumerate(xs)
24+
T = typeof(x)
2425
gv = mutable(v,i)
25-
gv[] = typeof(x) # init type
26-
gv[] = x # init value
26+
gv[] = T # init type
27+
gv[T] = x # init value
2728
end
2829
finalizer(v, (v)->for i = 1:length(v)
2930
ccall((:g_value_unset,libgobject),Void,(Ptr{GValue},),pointer(v,i))
3031
end)
3132
v
3233
end
3334

35+
function setindex!(dest::GV, src::GV)
36+
bool(ccall((:g_value_transform,libgobject),Cint,(Ptr{GValue},Ptr{GValue}),src,dest))
37+
src
38+
end
39+
40+
setindex!(::Type{Void},v::GV) = v
41+
setindex!(v::GLib.GV, x) = setindex!(v, x, typeof(x))
42+
setindex!(gv::GV, x, i::Int) = setindex!(mutable(gv,i), x)
43+
44+
getindex{T}(gv::GV, i::Int, ::Type{T}) = getindex(mutable(gv,i), T)
45+
getindex(gv::GV, i::Int) = getindex(mutable(gv,i))
46+
getindex(v::GV,i::Int, ::Type{Void}) = nothing
47+
3448
#let
3549
#global make_gvalue, getindex
3650
function make_gvalue(pass_x,as_ctype,to_gtype,with_id,allow_reverse::Bool=true,fundamental::Bool=false)
@@ -44,32 +58,39 @@ function make_gvalue(pass_x,as_ctype,to_gtype,with_id,allow_reverse::Bool=true,f
4458
ccall((:g_value_init,GLib.libgobject),Void,(Ptr{GLib.GValue},Csize_t), v, $with_id)
4559
v
4660
end
47-
function Base.setindex!{T<:$pass_x}(v::GLib.GV, x::T)
48-
$(if to_gtype == :string; :(x = GLib.bytestring(x)) end)
49-
$(if to_gtype == :pointer || to_gtype == :boxed; :(x = GLib.mutable(x)) end)
61+
function Base.setindex!{T<:$pass_x}(v::GLib.GV, x, ::Type{T})
62+
$( if to_gtype == :string
63+
:(x = GLib.bytestring(x))
64+
elseif to_gtype == :pointer || to_gtype == :boxed
65+
:(x = GLib.mutable(x))
66+
elseif to_gtype == :gtype
67+
:(x = GLib.g_type(x))
68+
end)
5069
ccall(($(string("g_value_set_",to_gtype)),GLib.libgobject),Void,(Ptr{GLib.GValue},$as_ctype), v, x)
5170
if isa(v, GLib.MutableTypes.MutableX)
5271
finalizer(v, (v::GLib.MutableTypes.MutableX)->ccall((:g_value_unset,GLib.libgobject),Void,(Ptr{GLib.GValue},), v))
5372
end
5473
v
5574
end
5675
end)
57-
if to_gtype == :static_string
58-
to_gtype = :string
59-
end
76+
end
77+
if to_gtype == :static_string
78+
to_gtype = :string
79+
end
80+
if pass_x !== None
6081
eval(current_module(),quote
6182
function Base.getindex{T<:$pass_x}(v::GLib.GV,::Type{T})
6283
x = ccall(($(string("g_value_get_",to_gtype)),GLib.libgobject),$as_ctype,(Ptr{GLib.GValue},), v)
63-
$(if to_gtype == :string; :(x = GLib.bytestring(x)) end)
64-
$(if pass_x == Symbol; :(x = symbol(x)) end)
84+
$( if to_gtype == :string
85+
:(x = GLib.bytestring(x))
86+
elseif pass_x == Symbol
87+
:(x = symbol(x))
88+
end)
6589
return Base.convert(T,x)
6690
end
6791
end)
6892
end
6993
if fundamental || allow_reverse
70-
if to_gtype == :static_string
71-
to_gtype = :string
72-
end
7394
fn = eval(current_module(),quote
7495
function(v::GLib.GV)
7596
x = ccall(($(string("g_value_get_",to_gtype)),GLib.libgobject),$as_ctype,(Ptr{GLib.GValue},), v)
@@ -86,53 +107,42 @@ function make_gvalue(pass_x,as_ctype,to_gtype,with_id,allow_reverse::Bool=true,f
86107
end
87108
end
88109
const gvalue_types = {}
89-
const fundamental_ids = tuple(Int[g_type_from_name(name) for (name,c,j,f) in fundamental_types]...)
90110
const fundamental_fns = tuple(Function[make_gvalue(juliatype, ctype, g_value_fn, fundamental_ids[i], false, true) for
91111
(i,(name, ctype, juliatype, g_value_fn)) in enumerate(fundamental_types)]...)
92-
make_gvalue(Symbol, Ptr{Uint8}, :static_string, :gstring_id, false)
112+
make_gvalue(Symbol, Ptr{Uint8}, :static_string, :(g_type(String)), false)
113+
make_gvalue(Type, GType, :gtype, (:g_gtype,:libgobject))
93114

94115
function getindex(gv::Union(Mutable{GValue}, Ptr{GValue}))
95-
g_type = unsafe_load(gv).g_type
96-
if g_type == 0
116+
gtyp = unsafe_load(gv).g_type
117+
if gtyp == 0
97118
error("Invalid GValue type")
98119
end
99-
if g_type == gvoid_id
120+
if gtyp == g_type(Void)
100121
return nothing
101122
end
102123
# first pass: fast loop for fundamental types
103124
for (i,id) in enumerate(fundamental_ids)
104-
if id == g_type # if g_type == id
125+
if id == gtyp # if g_type == id
105126
return fundamental_fns[i](gv)
106127
end
107128
end
108129
# second pass: user defined (sub)types
109130
for (typ, typefn, getfn) in gvalue_types
110-
if bool(ccall((:g_type_is_a,libgobject),Cint,(Int,Int),g_type,typefn())) # if g_type <: expr()
131+
if bool(ccall((:g_type_is_a,libgobject),Cint,(Int,Int),gtyp,typefn())) # if gtyp <: expr()
111132
return getfn(gv)
112133
end
113134
end
114135
# last pass: check for derived fundamental types (which have not been overridden by the user)
115136
for (i,id) in enumerate(fundamental_ids)
116-
if bool(ccall((:g_type_is_a,libgobject),Cint,(Int,Int),g_type,id)) # if g_type <: id
137+
if bool(ccall((:g_type_is_a,libgobject),Cint,(Int,Int),gtyp,id)) # if gtyp <: id
117138
return fundamental_fns[i](gv)
118139
end
119140
end
120-
typename = g_type_name(g_type)
141+
typename = g_type_name(gtyp)
121142
error("Could not convert GValue of type $typename to Julia type")
122143
end
123144
#end
124145

125-
function setindex!(dest::GV, src::GV)
126-
bool(ccall((:g_value_transform,libgobject),Cint,(Ptr{GValue},Ptr{GValue}),src,dest))
127-
src
128-
end
129-
130-
setindex!(::Type{Void},v::GV) = v
131-
setindex!(gv::GV, i::Int, x) = setindex!(mutable(gv,i), x)
132-
getindex{T}(gv::GV, i::Int, ::Type{T}) = getindex(mutable(gv,i), T)
133-
getindex(gv::Union(Mutable{GValue}, Ptr{GValue}), i::Int) = getindex(mutable(gv,i))
134-
getindex(v::GV,i::Int,::Type{Void}) = nothing
135-
136146
function getindex{T}(w::GObject, name::Union(String,Symbol), ::Type{T})
137147
v = gvalue(T)
138148
ccall((:g_object_get_property,libgobject), Void,
@@ -167,13 +177,12 @@ function show(io::IO, w::GObject)
167177
const READABLE=1
168178
if (param.flags&1)==READABLE &&
169179
bool(ccall((:g_value_type_transformable,libgobject),Cint,
170-
(Int,Int),param.value_type,gstring_id))
180+
(Int,Int),param.value_type,g_type(String)))
171181
ccall((:g_object_get_property,libgobject), Void,
172182
(Ptr{GObject}, Ptr{Uint8}, Ptr{GValue}), w, param.name, v)
173183
str = ccall((:g_value_get_string,libgobject),Ptr{Uint8},(Ptr{GValue},), v)
174184
value = (str == C_NULL ? "NULL" : bytestring(str))
175-
ccall((:g_value_reset,libgobject),Ptr{Void},(Ptr{GValue},), v)
176-
if param.value_type == gstring_id && str != C_NULL
185+
if param.value_type == g_type(String) && str != C_NULL
177186
print(io,"=\"",value,'"')
178187
else
179188
print(io,'=',value)
@@ -194,8 +203,8 @@ end
194203
# instance_size::Cuint
195204
# GTypeQuery() = new(0,0,0,0)
196205
#end
197-
#function gsizeof(g_type)
206+
#function gsizeof(gtyp)
198207
# q = mutable(GTypeQuery)
199-
# ccall((:g_type_query,libgobject),Void,(Int,Ptr{GTypeQuery},),g_type,q)
208+
# ccall((:g_type_query,libgobject),Void,(Int,Ptr{GTypeQuery},),gtyp,q)
200209
# q[].instance_size
201210
#end

src/GLib/signals.jl

+6-6
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@ function GClosureMarshal(closuref, return_value, n_param_values,
6767
length(param_types)+1 == n_param_values || error("GCallback called with the wrong number of parameters")
6868
for i = 1:n_param_values
6969
gv = mutable(param_values,i)
70-
g_type = unsafe_load(gv).g_type
70+
gtyp = unsafe_load(gv).g_type
7171
# avoid auto-unboxing for some builtin types in gtk_calling_convention mode
72-
if bool(ccall((:g_type_is_a,libgobject),Cint,(Int,Int),g_type,gobject_id))
72+
if bool(ccall((:g_type_is_a,libgobject),Cint,(Int,Int),gtyp,g_type(GObject)))
7373
params[i] = ccall((:g_value_get_object,libgobject), Ptr{GObject}, (Ptr{GValue},), gv)
74-
elseif bool(ccall((:g_type_is_a,libgobject),Cint,(Int,Int),g_type,gboxed_id))
74+
elseif bool(ccall((:g_type_is_a,libgobject),Cint,(Int,Int),gtyp,gboxed_id))
7575
params[i] = ccall((:g_value_get_boxed,libgobject), Ptr{Void}, (Ptr{GValue},), gv)
76-
elseif bool(ccall((:g_type_is_a,libgobject),Cint,(Int,Int),g_type,gstring_id))
76+
elseif bool(ccall((:g_type_is_a,libgobject),Cint,(Int,Int),gtyp,g_type(String)))
7777
params[i] = ccall((:g_value_get_string,libgobject), Ptr{Void}, (Ptr{GValue},), gv)
7878
else
7979
params[i] = gv[]
@@ -90,8 +90,8 @@ function GClosureMarshal(closuref, return_value, n_param_values,
9090
end
9191
retval = cb(params...) # widget, args...
9292
if return_value != C_NULL && retval !== nothing
93-
g_type = unsafe_load(return_value).g_type
94-
if g_type != gvoid_id && g_type != 0
93+
gtyp = unsafe_load(return_value).g_type
94+
if gtyp != g_type(Void) && gtyp != 0
9595
return_value[] = gvalue(retval)
9696
end
9797
end

0 commit comments

Comments
 (0)