Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,21 @@ jobs:
fail-fast: false
matrix:
version:
- '1.8'
- '1.9'
- '1.10'
- '1'
- 'nightly'
os:
- ubuntu-latest
- macOS-latest
- macos-latest
- windows-latest
arch:
- x64
arch: [x64, arm64]
exclude:
- os: ubuntu-latest
arch: arm64
- os: windows-latest
arch: arm64
- os: macos-latest
arch: x64
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -34,18 +40,13 @@ jobs:
repository: JuliaInterop/libcxxwrap-julia
path: libcxxwrap
- name: Install Qt
uses: jurplel/install-qt-action@v3
with:
version: '6.4.2'
uses: jurplel/install-qt-action@v4
- uses: julia-actions/setup-julia@latest
with:
version: ${{ matrix.version }}
arch: ${{ matrix.arch }}
- name: Build libcxxwrap-julia
run: |
if [[ "$OSTYPE" != "darwin"* ]]; then
rm -f /opt/hostedtoolcache/julia/1.6*/x64/lib/julia/libstdc++.so.6
fi
mkdir build-libcxxwrap && cd build-libcxxwrap
cmake -DCMAKE_INSTALL_PREFIX=$HOME/install -DJLCXX_BUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Debug ../libcxxwrap
VERBOSE=ON cmake --build . --config Debug --target install
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16.0)

project(JlQML)

set(JlQML_VERSION 0.7.0)
set(JlQML_VERSION 0.7.1)
message(STATUS "Project version: v${JlQML_VERSION}")

set(CMAKE_MACOSX_RPATH 1)
Expand Down
19 changes: 16 additions & 3 deletions jlqml.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,21 @@
#include <jlcxx/functions.hpp>
#include <QMetaType>

Q_DECLARE_METATYPE(jlcxx::SafeCFunction)
Q_DECLARE_OPAQUE_POINTER(jl_value_t*)
Q_DECLARE_METATYPE(jl_value_t*)
namespace qmlwrap
{

// Helper to store a Julia value of type Any in a GC-safe way
struct QVariantAny
{
QVariantAny(jl_value_t* v);
~QVariantAny();
jl_value_t* value;
};

using qvariant_any_t = std::shared_ptr<QVariantAny>;

}

Q_DECLARE_METATYPE(qmlwrap::qvariant_any_t)

#endif
45 changes: 40 additions & 5 deletions makie_viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@ namespace qmlwrap
class MakieRenderFunction : public RenderFunction
{
public:
MakieRenderFunction(jl_value_t* const & screen_ptr) : m_screen_ptr(screen_ptr)
MakieRenderFunction(jl_value_t* const & screen_ptr, jl_value_t*& scene) : m_screen_ptr(screen_ptr), m_scene(scene)
{
if(MakieViewport::m_default_render_function.fptr != nullptr)
{
m_scene_render_function = jlcxx::make_function_pointer<void(jl_value_t*, jl_value_t*)>(MakieViewport::m_default_render_function);
}
}

void setRenderFunction(jlcxx::SafeCFunction f) override
Expand All @@ -23,12 +27,22 @@ class MakieRenderFunction : public RenderFunction
}
void render() override
{
m_render_function(m_screen_ptr);
if(m_scene != nullptr)
{
m_scene_render_function(m_screen_ptr, m_scene);
}
else if(m_render_function != nullptr)
{
m_render_function(m_screen_ptr);
}
}
private:
typedef void (*render_callback_t)(jl_value_t*);
render_callback_t m_render_function;
render_callback_t m_render_function = nullptr;
typedef void (*scene_render_callback_t)(jl_value_t*, jl_value_t*); // Default render function takes an extra scene argument
scene_render_callback_t m_scene_render_function;
jl_value_t* const & m_screen_ptr;
jl_value_t*& m_scene;
};

jl_module_t* get_makie_support_module()
Expand Down Expand Up @@ -73,7 +87,7 @@ struct MakieSupport
jlcxx::JuliaFunction on_context_destroy;
};

MakieViewport::MakieViewport(QQuickItem *parent) : OpenGLViewport(parent, new MakieRenderFunction(m_screen))
MakieViewport::MakieViewport(QQuickItem *parent) : OpenGLViewport(parent, new MakieRenderFunction(m_screen, m_scene))
{
get_makie_support_module(); // Throw the possible error early
QObject::connect(this, &QQuickItem::windowChanged, [this] (QQuickWindow* w)
Expand All @@ -96,13 +110,33 @@ MakieViewport::~MakieViewport()
{
jlcxx::unprotect_from_gc(m_screen);
}
if(m_scene != nullptr)
{
jlcxx::unprotect_from_gc(m_scene);
}
}

qvariant_any_t MakieViewport::scene()
{
return std::make_shared<QVariantAny>(m_scene);
}

void MakieViewport::setScene(qvariant_any_t scene)
{
jl_value_t* scene_val = scene->value;
jlcxx::protect_from_gc(scene_val);
if(m_scene != nullptr)
{
jlcxx::unprotect_from_gc(m_scene);
}
m_scene = scene_val;
}

void MakieViewport::setup_buffer(QOpenGLFramebufferObject* fbo)
{
if(m_screen == nullptr)
{
m_screen = MakieSupport::instance().setup_screen(std::forward<QOpenGLFramebufferObject*>(fbo));
m_screen = MakieSupport::instance().setup_screen(std::forward<QOpenGLFramebufferObject*>(fbo), window());
jlcxx::protect_from_gc(m_screen);
}
else
Expand All @@ -113,5 +147,6 @@ void MakieViewport::setup_buffer(QOpenGLFramebufferObject* fbo)
}

jl_module_t* MakieViewport::m_qmlmakie_mod = nullptr;
jlcxx::SafeCFunction MakieViewport::m_default_render_function = {nullptr, nullptr, nullptr};

} // namespace qmlwrap
9 changes: 9 additions & 0 deletions makie_viewport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,23 @@ class MakieViewport : public OpenGLViewport
{
Q_OBJECT
QML_ELEMENT
Q_PROPERTY(qvariant_any_t scene READ scene WRITE setScene NOTIFY sceneChanged)
public:
MakieViewport(QQuickItem* parent = 0);
virtual ~MakieViewport();
qvariant_any_t scene();
void setScene(qvariant_any_t scene);

static jl_module_t* m_qmlmakie_mod;
static jlcxx::SafeCFunction m_default_render_function;

signals:
void sceneChanged();

private:
// Screen created and used on the Julia side
jl_value_t* m_screen = nullptr;
jl_value_t* m_scene = nullptr;
virtual void setup_buffer(QOpenGLFramebufferObject* fbo) override;
};

Expand Down
2 changes: 1 addition & 1 deletion opengl_viewport.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include <QOpenGLFramebufferObject>
#include <QQuickFramebufferObject>

// #include "jlqml.hpp"
#include "jlqml.hpp"

namespace qmlwrap
{
Expand Down
73 changes: 73 additions & 0 deletions qmltests/crash.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using QML

# const qml_file = joinpath(pwd(), "code", "qml", "test.qml")

function update_props()
props["fruits"] = fruits2
end

function main(qml_file, props)
loadqml(qml_file, props=props)
exec()
end

mutable struct Fruit
name::String
cost::Float64
end

fruits = JuliaItemModel([Fruit("apple", 1.0), Fruit("orange", 2.0)])
fruits2 = JuliaItemModel([Fruit("banana", 1.0), Fruit("pear", 2.0)])

props = JuliaPropertyMap("fruits" => fruits)

@qmlfunction update_props

# main(qml_file, props)


mktempdir() do folder
path = joinpath(folder, "test.qml")
write(
path,
"""
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import org.julialang

ApplicationWindow {
id: mainWin
title: "My Application"
width: 400
height: 400
visible: true

ColumnLayout{
anchors.fill: parent

Button {
height: 200
Layout.fillWidth: true
text: "Update Fruit"
onClicked: {
Julia.update_props()
console.log("Value:", props.fruits)
}
}
ListView {
model: props.fruits
Layout.fillHeight: true
Layout.fillWidth: true
delegate: Row {
Text {
text: name
}
}
}
}
}
"""
)
main(path, props)
end
31 changes: 11 additions & 20 deletions wrap_qml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,29 +51,15 @@ template<> struct SuperType<qmlwrap::JuliaItemModel> { using type = QAbstractTab
namespace qmlwrap
{

// Helper to store a Julia value of type Any in a GC-safe way
struct QVariantAny
QVariantAny::QVariantAny(jl_value_t* v) : value(v)
{
QVariantAny(jl_value_t* v) : value(v)
{
assert(v != nullptr);
jlcxx::protect_from_gc(value);
}
~QVariantAny()
{
jlcxx::unprotect_from_gc(value);
}
jl_value_t* value;
};

using qvariant_any_t = std::shared_ptr<QVariantAny>;

assert(v != nullptr);
jlcxx::protect_from_gc(value);
}

Q_DECLARE_METATYPE(qmlwrap::qvariant_any_t)

namespace qmlwrap
QVariantAny::~QVariantAny()
{
jlcxx::unprotect_from_gc(value);
}

using qvariant_types = jlcxx::ParameterList<bool, float, double, int32_t, int64_t, uint32_t, uint64_t, void*, jl_value_t*,
QString, QUrl, jlcxx::SafeCFunction, QVariantMap, QVariantList, QStringList, QList<QUrl>, JuliaDisplay*, JuliaCanvas*, JuliaPropertyMap*, QObject*>;
Expand Down Expand Up @@ -296,6 +282,11 @@ JLCXX_MODULE define_julia_module(jlcxx::Module& qml_module)
qmlwrap::MakieViewport::m_qmlmakie_mod = reinterpret_cast<jl_module_t*>(mod);
});

qml_module.method("set_default_makie_renderfunction", [](jlcxx::SafeCFunction renderFunction)
{
qmlwrap::MakieViewport::m_default_render_function = renderFunction;
});

// Enums
qml_module.add_bits<Qt::Orientation>("Orientation", jlcxx::julia_type("CppEnum"));
qml_module.set_const("Horizontal", Qt::Horizontal);
Expand Down
Loading