Properties passed to `loadqml` makes app to crash when loaded from module
JanisErdmanis opened this issue · comments
In the current master version of QML, in a situation where an application code is placed within a module exposing a julia_main
function to start the application, there happens to be a crash when this julia_main
function is called. As an example, consider the following:
module QMLApp
using QML
const _PROPERTIES = JuliaPropertyMap(
"text" => "Hello World Again!",
"count" => 16
)
function julia_main()::Cint
loadqml((@__DIR__) * "/App.qml"; _PROPERTIES)
exec()
return 0
end
end # module QMLApp
When called from a module with using QMLApp; QMLApp.julia_main()
a following error happens:
ERROR: C++ object of type N7qmlwrap16JuliaPropertyMapE was deleted
Stacktrace:
[1] cxxupcast
@ ~/.julia/packages/CxxWrap/aXNBY/src/CxxWrap.jl:624 [inlined]
[2] cxxupcast
@ ~/.julia/packages/CxxWrap/aXNBY/src/CxxWrap.jl:274 [inlined]
[3] cxxupcast
@ ~/.julia/packages/CxxWrap/aXNBY/src/CxxWrap.jl:277 [inlined]
[4] convert
@ ~/.julia/packages/CxxWrap/aXNBY/src/CxxWrap.jl:682 [inlined]
[5] cxxconvert
@ ~/.julia/packages/CxxWrap/aXNBY/src/CxxWrap.jl:582 [inlined]
[6] cconvert
@ ~/.julia/packages/CxxWrap/aXNBY/src/CxxWrap.jl:558 [inlined]
[7] _set_context_property
@ ~/.julia/packages/CxxWrap/aXNBY/src/CxxWrap.jl:624 [inlined]
[8] set_context_property(ctx::QML.QQmlContextDereferenced, name::String, value::QML._JuliaPropertyMapAllocated)
@ QML ~/.julia/packages/CxxWrap/aXNBY/src/CxxWrap.jl:61
[9] set_context_property(ctx::CxxWrap.CxxWrapCore.CxxPtr{QML.QQmlContext}, name::String, jpm::QML.JuliaPropertyMap)
@ QML ~/.julia/packages/CxxWrap/aXNBY/src/CxxWrap.jl:408
[10] loadqml(qmlfilename::String; kwargs::Base.Pairs{Symbol, QML.JuliaPropertyMap, Tuple{Symbol}, NamedTuple{(:_PROPERTIES,), Tuple{QML.JuliaPropertyMap}}})
@ QML ~/.julia/packages/QML/dFnTL/src/QML.jl:90
[11] loadqml
@ ~/.julia/packages/QML/dFnTL/src/QML.jl:86 [inlined]
[12] julia_main()
@ QMLApp ~/BtSync/PeaceFounder/SandBox/QMLApp/src/QMLApp.jl:14
[13] top-level scope
@ REPL[2]:1
This error does not happen if the _PROPERTIES
are not passed to loadqml
. Also, interestingly, the code works fine when the module is included within a file like include("src/QMLApp.jl"); QMLApp.julia_main()
.
A full self-contained example is available at https://github.com/JanisErdmanis/QMLAppTest/tree/julia_main_bug
Can you replicate the issue with QML 0.8?
Yes, I just tested it with Julia 1.9.2 and QML 0.8. The error is still there.
Which operating system are you using?
MacOS 14 on Apple silicon. I will check it later on Ubuntu.
I can report that the problem persists when using Ubuntu 22.10 with Julia 1.9.3 and the current QML 0.8 version.
The reason for this is that _PROPERTIES
actually stores a pointer to a C++ object, so it stores a pointer during precompilation that is then used in a later run, but of course no longer valid. To work around that you can return _PROPPERTIES
from a function instead of making it a module constant.
The new documentation at https://juliagraphics.github.io/QML.jl/dev/#Using-QML.jl-inside-another-Julia-module should make this clearer, so I'm closing this.
This makes sense. Another workaround I just tested is that one can define the relevant global variables in the __init__
block:
module QMLApp
using QML
function __init__()
global PROPERTIES = JuliaPropertyMap(
"text" => "Hello World Again!",
"count" => 16
)
end
function julia_main()::Cint
loadqml((@__DIR__) * "/App.qml"; PROPERTIES)
exec()
return 0
end
end
This makes it easier to structure larger applications where passing multiple properties to every function would be cumbersome. It also seems necessary for processing signals on the Julia side, which updates the model and ultimately from which QML redraws the view.
Indeed, good solution!