Skip to content

Commit 1c973b4

Browse files
authored
use libgirepository in Glib_jll >=2.80 (#107)
In GLib 2.80, libgirepository was moved in from gobject-introspection and rewritten. This adapts GI.jl to use it. For some reason, if the generation scripts are run sequentially in the same Julia session, as was done in "gen_all.jl", libgirepository can't reliably figure out what shared library is associated with a given namespace. I assume this can be fixed here but for now we will have to run the generation script for each namespace in a separate Julia session.
1 parent fe7cf19 commit 1c973b4

27 files changed

+901
-773
lines changed

GI/Project.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,13 @@ EzXML = "8f5d6c58-4d21-5cfd-889c-e3ad7ee6a615"
99
Glib_jll = "7746bdde-850d-59dc-9ae8-88ece973131d"
1010
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
1111
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
12-
gobject_introspection_jll = "6306888c-5478-5f78-9aeb-34cb5688c579"
1312

1413
[compat]
15-
julia = "1.6"
14+
julia = "1.10"
1615
BitFlags = "0.1.5"
1716
CEnum = "0.4, 0.5"
1817
EzXML = "1"
19-
Glib_jll = "2.74.0"
20-
Libdl = "1.6"
18+
Glib_jll = "2.82.0"
19+
Libdl = "1.10"
2120
MacroTools = "0.5"
22-
gobject_introspection_jll = "1.74"
21+

GI/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
GI.jl
22
======
33

4-
Julia bindings using libgobject-introspection.
4+
Julia bindings using GObject introspection.
55

66
This builds on https://github.com/bfredl/GI.jl
77

@@ -15,7 +15,7 @@ As new functionality is added to libraries, you just have to run GI.jl again and
1515
The advantage over using Clang to generate wrappers is the fact that annotations provide important information, like whether outputs are "owned" or not, which arguments are closures or array lengths, and so on.
1616
Disadvantages: the current implementation only extracts GI information on Linux, leading to potential bugs on other platforms.
1717

18-
This package is unregistered and it only works on Linux because it uses [gobject_introspection_jll](https://github.com/JuliaPackaging/Yggdrasil/tree/master/G/gobject_introspection), which is currently only available for Linux. However, most generated code works on other platforms.
18+
This package is unregistered. It has only been tested and run on Linux. However, most generated code works on other platforms.
1919

2020
## Status
2121

GI/src/GI.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
module GI
2-
using Glib_jll, gobject_introspection_jll
2+
using Glib_jll
33
using MacroTools, CEnum, BitFlags, EzXML
44

5-
@static gobject_introspection_jll.is_available() || error("gobject_introspection_jll is not available on this platform")
6-
75
include("GLibBase/GLibBase.jl")
86

97
import .GLibBase as GLib
@@ -23,16 +21,18 @@ module GI
2321
export const_expr
2422
export extract_type
2523

26-
libgi = gobject_introspection_jll.libgirepository
27-
28-
global const libgi_version = VersionNumber(
29-
ccall((:gi_get_major_version, libgi), Cint, ()),
30-
ccall((:gi_get_minor_version, libgi), Cint, ()),
31-
ccall((:gi_get_micro_version, libgi), Cint, ()))
32-
24+
const libgi = Glib_jll.libgirepository
25+
mutable struct GIRepository
26+
handle::Ptr{GIRepository}
27+
end
3328

29+
global repo::GIRepository
3430
include("girepo.jl")
3531
include("giimport.jl")
3632
include("giexport.jl")
3733
include("gidocs.jl")
34+
35+
function __init__()
36+
global repo = GIRepository()
37+
end
3838
end

GI/src/GLibBase/GLibBase.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@ export GList, _GSList, _GList
2020
const AbstractStringLike = Union{AbstractString, Symbol}
2121
bytestring(s) = String(s)
2222
bytestring(s::Symbol) = s
23-
bytestring(s::Ptr{UInt8}) = s == C_NULL ? nothing : unsafe_string(s)
23+
function bytestring(s::Union{Cstring,Ptr{UInt8}}, own::Bool=false)
24+
str=unsafe_string(s)
25+
if own
26+
g_free(s)
27+
end
28+
str
29+
end
30+
2431
# bytestring(s::Ptr{UInt8}, own::Bool=false) = unsafe_string(s)
2532

2633
g_free(p::Ptr) = ccall((:g_free, libglib), Nothing, (Ptr{Nothing},), p)

GI/src/giexport.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ function all_objects!(exprs,exports,ns;print_summary=true,handled=Symbol[],skipl
309309
imported -= 1
310310
continue
311311
end
312-
if get_type_init(o)==:intern # GParamSpec and children output this
312+
if get_type_init_function_name(o)==:intern # GParamSpec and children output this
313313
continue
314314
end
315315
obj_decl!(exprs,o,ns,handled)
@@ -453,11 +453,11 @@ function all_functions!(exprs,ns;print_summary=true,skiplist=Symbol[],symbol_ski
453453
unsupported = false # whatever we happen to unsupport
454454
for arg in get_args(i)
455455
try
456-
bt = get_base_type(get_type(arg))
456+
bt = get_base_type(get_type_info(arg))
457457
if isa(bt,Ptr{GIArrayType}) || isa(bt,Ptr{GIArrayType{3}})
458458
unsupported = true; break
459459
end
460-
if (isa(get_base_type(get_type(arg)), Nothing))
460+
if (isa(get_base_type(get_type_info(arg)), Nothing))
461461
unsupported = true; break
462462
end
463463
catch e

GI/src/giimport.jl

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@ end
1414
find_symbol(id) = Base.Fix2(find_symbol, id)
1515

1616
function typeinit_def(info, gstructname = get_name(info))
17-
type_init = String(get_type_init(info))
18-
libs=get_shlibs(GINamespace(get_namespace(info)))
19-
lib=libs[findfirst(find_symbol(type_init),libs)]
17+
type_init = String(get_type_init_function_name(info))
18+
libs=get_shlibs(info)
19+
ind = findfirst(find_symbol(type_init),libs)
20+
isnothing(ind) && error("function $(type_init) not found in $libs")
21+
lib=libs[ind]
2022
quote
2123
GLib.g_type(::Type{T}) where {T <: $gstructname} =
2224
ccall(($type_init, $(symbol_from_lib(lib))), GType, ())
@@ -26,7 +28,7 @@ end
2628
function append_type_init(body, enum, incl_typeinit)
2729
bloc = Expr(:block, unblock(body))
2830
# if this enum has a GType we define GLib.g_type() to support storing this in GValue
29-
if incl_typeinit && get_type_init(enum) !== :nothing
31+
if incl_typeinit && get_type_init_function_name(enum) !== :nothing
3032
push!(bloc.args,unblock(typeinit_def(enum)))
3133
end
3234
unblock(bloc)
@@ -305,7 +307,7 @@ end
305307
function decl(interfaceinfo::GIInterfaceInfo)
306308
g_type = get_g_type(interfaceinfo)
307309

308-
type_init = Symbol(get_type_init(interfaceinfo))
310+
type_init = Symbol(get_type_init_function_name(interfaceinfo))
309311
libs=get_shlibs(GINamespace(get_namespace(interfaceinfo)))
310312
lib=libs[findfirst(find_symbol(type_init),libs)]
311313

@@ -442,15 +444,15 @@ end
442444
# used for certain types to convert returned values from ccall's to Julia types
443445

444446
function extract_type(info::GIArgInfo)
445-
typdesc = extract_type(get_type(info))
447+
typdesc = extract_type(get_type_info(info))
446448
if may_be_null(info) && typdesc.jtype !== :Any
447449
jtype=typdesc.jtype
448450
typdesc.jtype = :(Maybe($jtype))
449451
typdesc.jstype = :($jtype)
450452
end
451453
typdesc
452454
end
453-
extract_type(info::GIFieldInfo) = extract_type(get_type(info))
455+
extract_type(info::GIFieldInfo) = extract_type(get_type_info(info))
454456
function extract_type(info::GITypeInfo)
455457
base_type = get_base_type(info)
456458
extract_type(info,base_type)
@@ -563,14 +565,14 @@ function convert_from_c(name::Symbol, arginfo::ArgInfo, typeinfo::TypeDesc{T}) w
563565
if typeof(arginfo)==GIFunctionInfo
564566
argtypeinfo=get_return_type(arginfo)
565567
else
566-
argtypeinfo=get_type(arginfo)
568+
argtypeinfo=get_type_info(arginfo)
567569
end
568570
elm = get_param_type(argtypeinfo,0)
569571
elmtype = extract_type(elm)
570572
elmctype=elmtype.ctype
571-
arrlen=get_array_length(argtypeinfo) # position of array length argument
573+
arrlen=get_array_length_index(argtypeinfo) # position of array length argument
572574
lensymb=nothing
573-
if arrlen != -1
575+
if arrlen !== nothing
574576
if typeof(arginfo)==GIFunctionInfo
575577
args=get_args(arginfo)
576578
else
@@ -641,7 +643,7 @@ function convert_to_c(name::Symbol, info::GIArgInfo, ti::TypeDesc{T}) where {T<:
641643
return (name, nothing)
642644
end
643645
is_caller_allocates(info) && throw(NotImplementedException("Array output with 'caller_allocates'"))
644-
typeinfo=get_type(info)
646+
typeinfo=get_type_info(info)
645647
elm = get_param_type(typeinfo,0)
646648
elmtype = extract_type(elm)
647649
elmctype=elmtype.ctype
@@ -708,10 +710,10 @@ callback_symbols(name) = (Symbol("$(name)_cfunc"),Symbol("$(name)_closure"),Symb
708710

709711
function convert_to_c(name::Symbol, info::GIArgInfo, ti::TypeDesc{T}) where {T<:Type{Function}}
710712
st = get_scope(info)
711-
closure = get_closure(info)
713+
closure = get_closure_index(info)
712714
(st == GIScopeType.FOREVER || st == GIScopeType.INVALID) && throw(NotImplementedError("Scope type $st not implemented."))
713-
closure == -1 && throw(NotImplementedError("Closure not found."))
714-
callbackinfo=get_interface(get_type(info))
715+
closure === nothing && throw(NotImplementedError("Closure not found."))
716+
callbackinfo=get_interface(get_type_info(info))
715717
# get return type
716718
rettyp=get_return_type(callbackinfo)
717719
cname=get_full_name(callbackinfo)
@@ -724,7 +726,7 @@ function convert_to_c(name::Symbol, info::GIArgInfo, ti::TypeDesc{T}) where {T<:
724726
if i == length(args) # we already know there is a closure, and it has to be the last argument
725727
push!(argctypes_arr,:(Ref{Function}))
726728
else
727-
argtyp=get_type(arg)
729+
argtyp=get_type_info(arg)
728730
argctyp=extract_type(argtyp).ctype
729731
push!(argctypes_arr,argctyp)
730732
end
@@ -870,7 +872,7 @@ end
870872

871873
function convert_from_c(name::Symbol, arginfo::ArgInfo, typeinfo::TypeDesc{T}) where {T <: Type{GBoxed}}
872874
owns = get_ownership_transfer(arginfo) != GITransfer.NOTHING
873-
typ = isa(arginfo, GIFunctionInfo) ? 0 : get_type(arginfo)
875+
typ = isa(arginfo, GIFunctionInfo) ? 0 : get_type_info(arginfo)
874876

875877
if may_be_null(arginfo)
876878
:(convert_if_not_null($(typeinfo.jstype), $name, $owns))
@@ -925,7 +927,7 @@ end
925927

926928
function convert_from_c(name::Symbol, arginfo::ArgInfo, ti::TypeDesc{T}) where {T}
927929
# check transfer
928-
typ=get_type(arginfo)
930+
typ=get_type_info(arginfo)
929931

930932
if ti.jtype !== :Any && ti.jtype !== :Real && ti.jtype !== :Integer
931933
:(convert($(ti.jtype), $name))
@@ -1034,8 +1036,8 @@ function get_closure_args(info::GIFunctionInfo)
10341036
for arg in get_args(info)
10351037
is_skip(arg) && continue
10361038
typ = extract_type(arg)
1037-
closure = get_closure(arg)
1038-
if typ.gitype == Function && closure > -1
1039+
closure = get_closure_index(arg)
1040+
if typ.gitype == Function && closure !== nothing
10391041
aname = Symbol("_", get_name(arg))
10401042
closure_args[aname]=closure+1
10411043
end
@@ -1070,9 +1072,9 @@ function get_jargs(info::GIFunctionInfo)
10701072
for arg in args
10711073
is_skip(arg) && continue
10721074
typ = extract_type(arg)
1073-
typeinfo=get_type(arg)
1074-
arrlen=get_array_length(typeinfo)
1075-
if typ.gitype == GICArray && arrlen >= 0
1075+
typeinfo=get_type_info(arg)
1076+
arrlen=get_array_length_index(typeinfo)
1077+
if typ.gitype == GICArray && arrlen !== nothing
10761078
len_name=Symbol("_",get_name(args[arrlen+1]))
10771079
len_i=findfirst(a->(a.name === len_name),jargs)
10781080
len_i !== nothing && deleteat!(jargs,len_i)
@@ -1191,7 +1193,7 @@ function create_method(info::GIFunctionInfo, liboverride = nothing)
11911193
else
11921194
ctype = typ.ctype
11931195
wname = Symbol("m_$(get_name(arg))")
1194-
atyp = get_type(arg)
1196+
atyp = get_type_info(arg)
11951197
push!(prologue, :( $wname = Ref{$ctype}() ))
11961198
if dir == GIDirection.INOUT
11971199
push!(prologue, :( $wname[] = Base.cconvert($ctype,$anametran) ))
@@ -1212,9 +1214,9 @@ function create_method(info::GIFunctionInfo, liboverride = nothing)
12121214
is_skip(arg) && continue
12131215
typ = extract_type(arg)
12141216
aname = Symbol("_$(get_name(arg))")
1215-
typeinfo=get_type(arg)
1216-
arrlen=get_array_length(typeinfo)
1217-
if typ.gitype == GICArray && arrlen >= 0
1217+
typeinfo=get_type_info(arg)
1218+
arrlen=get_array_length_index(typeinfo)
1219+
if typ.gitype == GICArray && arrlen !== nothing
12181220
len_name=Symbol("_",get_name(args[arrlen+1]))
12191221
len_i=findfirst(a->((Symbol("_$(get_name(a))") === len_name && get_direction(a) != GIDirection.OUT)),args)
12201222
if len_i !== nothing
@@ -1224,14 +1226,14 @@ function create_method(info::GIFunctionInfo, liboverride = nothing)
12241226
end
12251227
end
12261228
if rettype.gitype == GICArray
1227-
arrlen=get_array_length(rettypeinfo)
1228-
if arrlen >=0
1229+
arrlen=get_array_length_index(rettypeinfo)
1230+
if arrlen !== nothing
12291231
len_name=Symbol("_",get_name(args[arrlen+1]))
12301232
delete_arg!(retvals, len_name)
12311233
end
12321234
end
12331235

1234-
if flags & GIFunction.THROWS != 0
1236+
if can_throw_gerror(info)
12351237
push!(prologue, :( err = err_buf() ))
12361238
push!(cargs, Arg(:err, :(Ptr{Ptr{GError}})))
12371239
pushfirst!(epilogue, :( check_err(err) ))

0 commit comments

Comments
 (0)