mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 18:58:36 +00:00
Fix cross-compilation of C++ interpreter API to 32-bit architecture (#3810)
cbindgen doesn't reliably tranfser the 64-bit/32-bit #ifdefs around ValueOpaque. Instead, move Value onto the heap by using a Box. Fixes #3653
This commit is contained in:
parent
4b37d9a1f1
commit
1441719f61
4 changed files with 226 additions and 280 deletions
3
.github/workflows/yocto_build.yaml
vendored
3
.github/workflows/yocto_build.yaml
vendored
|
@ -20,7 +20,6 @@ jobs:
|
|||
- sdk_url: https://nextcloud.slint.dev/s/BTL5NtLACjgS7Pf/download/poky-glibc-x86_64-core-image-weston-cortexa15t2hf-neon-qemuarm-toolchain-4.0.9.sh
|
||||
env_setup: environment-setup-cortexa15t2hf-neon-poky-linux-gnueabi
|
||||
target: armv7-unknown-linux-gnueabihf
|
||||
extra_args: -DSLINT_FEATURE_INTERPRETER=OFF
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
@ -43,5 +42,5 @@ jobs:
|
|||
# f5c3908b7ec5131b7b19ff642b5975660c7484f8
|
||||
export BINDGEN_EXTRA_CLANG_ARGS=$OECORE_TUNE_CCARGS
|
||||
mkdir ${{ runner.workspace }}/cppbuild
|
||||
cmake -GNinja -B ${{ runner.workspace }}/cppbuild -S . -DRust_CARGO_TARGET=${{ matrix.target }} -DSLINT_BUILD_TESTING=ON -DSLINT_BUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Debug -DSLINT_FEATURE_RENDERER_SKIA=ON -DSLINT_FEATURE_BACKEND_QT=OFF -DSLINT_FEATURE_BACKEND_LINUXKMS=ON ${{ matrix.extra_args }}
|
||||
cmake -GNinja -B ${{ runner.workspace }}/cppbuild -S . -DRust_CARGO_TARGET=${{ matrix.target }} -DSLINT_BUILD_TESTING=ON -DSLINT_BUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Debug -DSLINT_FEATURE_RENDERER_SKIA=ON -DSLINT_FEATURE_BACKEND_QT=OFF -DSLINT_FEATURE_BACKEND_LINUXKMS=ON -DSLINT_FEATURE_INTERPRETER=ON
|
||||
cmake --build ${{ runner.workspace }}/cppbuild
|
||||
|
|
|
@ -768,13 +768,13 @@ fn gen_interpreter(
|
|||
dependencies: &mut Vec<PathBuf>,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut config = default_config();
|
||||
// Avoid Value, just export ValueOpaque.
|
||||
config.export.exclude = IntoIterator::into_iter([
|
||||
"Value",
|
||||
"ValueType",
|
||||
"PropertyDescriptor",
|
||||
"Diagnostic",
|
||||
"PropertyDescriptor",
|
||||
"Box",
|
||||
])
|
||||
.map(String::from)
|
||||
.collect();
|
||||
|
@ -795,7 +795,7 @@ fn gen_interpreter(
|
|||
"StructIteratorOpaque",
|
||||
"ComponentInstance",
|
||||
"StructIteratorResult",
|
||||
"ValueOpaque",
|
||||
"Value",
|
||||
"StructOpaque",
|
||||
"ModelNotifyOpaque",
|
||||
])
|
||||
|
@ -821,6 +821,7 @@ fn gen_interpreter(
|
|||
using slint::interpreter::ValueType;
|
||||
using slint::interpreter::PropertyDescriptor;
|
||||
using slint::interpreter::Diagnostic;
|
||||
template <typename T> using Box = T*;
|
||||
}",
|
||||
)
|
||||
.generate()
|
||||
|
|
|
@ -151,30 +151,17 @@ public:
|
|||
|
||||
private:
|
||||
cbindgen_private::StructIteratorOpaque inner;
|
||||
const Value *v = nullptr;
|
||||
Value *v = nullptr;
|
||||
std::string_view k;
|
||||
friend Struct;
|
||||
explicit iterator(cbindgen_private::StructIteratorOpaque inner) : inner(inner) { next(); }
|
||||
// construct a end iterator
|
||||
iterator() = default;
|
||||
void next()
|
||||
{
|
||||
auto next = cbindgen_private::slint_interpreter_struct_iterator_next(&inner);
|
||||
v = reinterpret_cast<const Value *>(next.v);
|
||||
k = std::string_view(reinterpret_cast<char *>(next.k.ptr), next.k.len);
|
||||
if (!v) {
|
||||
cbindgen_private::slint_interpreter_struct_iterator_destructor(&inner);
|
||||
}
|
||||
}
|
||||
inline void next();
|
||||
|
||||
public:
|
||||
/// Destroys this field iterator.
|
||||
~iterator()
|
||||
{
|
||||
if (v) {
|
||||
cbindgen_private::slint_interpreter_struct_iterator_destructor(&inner);
|
||||
}
|
||||
}
|
||||
inline ~iterator();
|
||||
// FIXME I believe iterators are supposed to be copy constructible
|
||||
iterator(const iterator &) = delete;
|
||||
iterator &operator=(const iterator &) = delete;
|
||||
|
@ -256,23 +243,23 @@ class Value
|
|||
{
|
||||
public:
|
||||
/// Constructs a new value of type Value::Type::Void.
|
||||
Value() { cbindgen_private::slint_interpreter_value_new(&inner); }
|
||||
Value() : inner(cbindgen_private::slint_interpreter_value_new()) { }
|
||||
|
||||
/// Constructs a new value by copying \a other.
|
||||
Value(const Value &other) { slint_interpreter_value_clone(&other.inner, &inner); }
|
||||
Value(const Value &other) : inner(slint_interpreter_value_clone(other.inner)) { }
|
||||
/// Constructs a new value by moving \a other to this.
|
||||
Value(Value &&other)
|
||||
{
|
||||
inner = other.inner;
|
||||
cbindgen_private::slint_interpreter_value_new(&other.inner);
|
||||
other.inner = cbindgen_private::slint_interpreter_value_new();
|
||||
}
|
||||
/// Assigns the value \a other to this.
|
||||
Value &operator=(const Value &other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
cbindgen_private::slint_interpreter_value_destructor(&inner);
|
||||
slint_interpreter_value_clone(&other.inner, &inner);
|
||||
cbindgen_private::slint_interpreter_value_destructor(inner);
|
||||
inner = slint_interpreter_value_clone(other.inner);
|
||||
return *this;
|
||||
}
|
||||
/// Moves the value \a other to this.
|
||||
|
@ -280,13 +267,13 @@ public:
|
|||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
cbindgen_private::slint_interpreter_value_destructor(&inner);
|
||||
cbindgen_private::slint_interpreter_value_destructor(inner);
|
||||
inner = other.inner;
|
||||
cbindgen_private::slint_interpreter_value_new(&other.inner);
|
||||
other.inner = cbindgen_private::slint_interpreter_value_new();
|
||||
return *this;
|
||||
}
|
||||
/// Destroys the value.
|
||||
~Value() { cbindgen_private::slint_interpreter_value_destructor(&inner); }
|
||||
~Value() { cbindgen_private::slint_interpreter_value_destructor(inner); }
|
||||
|
||||
/// A convenience alias for the value type enum.
|
||||
using Type = ValueType;
|
||||
|
@ -297,7 +284,7 @@ public:
|
|||
/// Type::Double, otherwise an empty optional is returned.
|
||||
std::optional<double> to_number() const
|
||||
{
|
||||
if (auto *number = cbindgen_private::slint_interpreter_value_to_number(&inner)) {
|
||||
if (auto *number = cbindgen_private::slint_interpreter_value_to_number(inner)) {
|
||||
return *number;
|
||||
} else {
|
||||
return {};
|
||||
|
@ -308,7 +295,7 @@ public:
|
|||
/// Type::String, otherwise an empty optional is returned.
|
||||
std::optional<slint::SharedString> to_string() const
|
||||
{
|
||||
if (auto *str = cbindgen_private::slint_interpreter_value_to_string(&inner)) {
|
||||
if (auto *str = cbindgen_private::slint_interpreter_value_to_string(inner)) {
|
||||
return *str;
|
||||
} else {
|
||||
return {};
|
||||
|
@ -319,7 +306,7 @@ public:
|
|||
/// Type::Bool, otherwise an empty optional is returned.
|
||||
std::optional<bool> to_bool() const
|
||||
{
|
||||
if (auto *b = cbindgen_private::slint_interpreter_value_to_bool(&inner)) {
|
||||
if (auto *b = cbindgen_private::slint_interpreter_value_to_bool(inner)) {
|
||||
return *b;
|
||||
} else {
|
||||
return {};
|
||||
|
@ -336,7 +323,7 @@ public:
|
|||
/// Type::Brush, otherwise an empty optional is returned.
|
||||
std::optional<slint::Brush> to_brush() const
|
||||
{
|
||||
if (auto *brush = cbindgen_private::slint_interpreter_value_to_brush(&inner)) {
|
||||
if (auto *brush = cbindgen_private::slint_interpreter_value_to_brush(inner)) {
|
||||
return *brush;
|
||||
} else {
|
||||
return {};
|
||||
|
@ -347,7 +334,7 @@ public:
|
|||
/// Type::Struct, otherwise an empty optional is returned.
|
||||
std::optional<Struct> to_struct() const
|
||||
{
|
||||
if (auto *opaque_struct = cbindgen_private::slint_interpreter_value_to_struct(&inner)) {
|
||||
if (auto *opaque_struct = cbindgen_private::slint_interpreter_value_to_struct(inner)) {
|
||||
return Struct(*opaque_struct);
|
||||
} else {
|
||||
return {};
|
||||
|
@ -358,7 +345,7 @@ public:
|
|||
/// Type::Image, otherwise an empty optional is returned.
|
||||
std::optional<Image> to_image() const
|
||||
{
|
||||
if (auto *img = cbindgen_private::slint_interpreter_value_to_image(&inner)) {
|
||||
if (auto *img = cbindgen_private::slint_interpreter_value_to_image(inner)) {
|
||||
return *reinterpret_cast<const Image *>(img);
|
||||
} else {
|
||||
return {};
|
||||
|
@ -368,66 +355,68 @@ public:
|
|||
// template<typename T> std::optional<T> get() const;
|
||||
|
||||
/// Constructs a new Value that holds the double \a value.
|
||||
Value(double value) { cbindgen_private::slint_interpreter_value_new_double(value, &inner); }
|
||||
Value(double value) : inner(cbindgen_private::slint_interpreter_value_new_double(value)) { }
|
||||
/// Constructs a new Value that holds the int \a value.
|
||||
/// Internally this is stored as a double and Value::type() will return Value::Type::Number.
|
||||
Value(int value) : Value(static_cast<double>(value)) { }
|
||||
/// Constructs a new Value that holds the string \a str.
|
||||
Value(const SharedString &str)
|
||||
: inner(cbindgen_private::slint_interpreter_value_new_string(&str))
|
||||
{
|
||||
cbindgen_private::slint_interpreter_value_new_string(&str, &inner);
|
||||
}
|
||||
/// Constructs a new Value that holds the boolean \a b.
|
||||
Value(bool b) { cbindgen_private::slint_interpreter_value_new_bool(b, &inner); }
|
||||
Value(bool b) : inner(cbindgen_private::slint_interpreter_value_new_bool(b)) { }
|
||||
/// Constructs a new Value that holds the value vector \a v as a model.
|
||||
inline Value(const SharedVector<Value> &v);
|
||||
/// Constructs a new Value that holds the value model \a m.
|
||||
Value(const std::shared_ptr<slint::Model<Value>> &m);
|
||||
/// Constructs a new Value that holds the brush \a b.
|
||||
Value(const slint::Brush &brush)
|
||||
: inner(cbindgen_private::slint_interpreter_value_new_brush(&brush))
|
||||
{
|
||||
cbindgen_private::slint_interpreter_value_new_brush(&brush, &inner);
|
||||
}
|
||||
/// Constructs a new Value that holds the Struct \a struc.
|
||||
Value(const Struct &struc)
|
||||
: inner(cbindgen_private::slint_interpreter_value_new_struct(&struc.inner))
|
||||
{
|
||||
cbindgen_private::slint_interpreter_value_new_struct(&struc.inner, &inner);
|
||||
}
|
||||
|
||||
/// Constructs a new Value that holds the Image \a img.
|
||||
Value(const Image &img) { cbindgen_private::slint_interpreter_value_new_image(&img, &inner); }
|
||||
Value(const Image &img) : inner(cbindgen_private::slint_interpreter_value_new_image(&img)) { }
|
||||
|
||||
/// Returns the type the variant holds.
|
||||
Type type() const { return cbindgen_private::slint_interpreter_value_type(&inner); }
|
||||
Type type() const { return cbindgen_private::slint_interpreter_value_type(inner); }
|
||||
|
||||
/// Returns true if \a a and \a b hold values of the same type and the underlying vales are
|
||||
/// equal.
|
||||
friend bool operator==(const Value &a, const Value &b)
|
||||
{
|
||||
return cbindgen_private::slint_interpreter_value_eq(&a.inner, &b.inner);
|
||||
return cbindgen_private::slint_interpreter_value_eq(a.inner, b.inner);
|
||||
}
|
||||
|
||||
private:
|
||||
inline Value(const void *) = delete; // Avoid that for example Value("foo") turns to Value(bool)
|
||||
using ValueOpaque = slint::cbindgen_private::ValueOpaque;
|
||||
ValueOpaque inner;
|
||||
slint::cbindgen_private::Value *inner;
|
||||
friend struct Struct;
|
||||
friend class ComponentInstance;
|
||||
// Internal constructor that takes ownership of the value
|
||||
explicit Value(ValueOpaque &inner) : inner(inner) { }
|
||||
explicit Value(slint::cbindgen_private::Value *&&inner) : inner(inner) { }
|
||||
};
|
||||
|
||||
inline Value::Value(const slint::SharedVector<Value> &array)
|
||||
: inner(cbindgen_private::slint_interpreter_value_new_array_model(
|
||||
reinterpret_cast<const slint::SharedVector<slint::cbindgen_private::Value *> *>(
|
||||
&array)))
|
||||
{
|
||||
cbindgen_private::slint_interpreter_value_new_array_model(
|
||||
reinterpret_cast<const slint::SharedVector<ValueOpaque> *>(&array), &inner);
|
||||
}
|
||||
|
||||
inline std::optional<slint::SharedVector<Value>> Value::to_array() const
|
||||
{
|
||||
slint::SharedVector<Value> array;
|
||||
if (cbindgen_private::slint_interpreter_value_to_array(
|
||||
&inner, reinterpret_cast<slint::SharedVector<ValueOpaque> *>(&array))) {
|
||||
&inner,
|
||||
reinterpret_cast<slint::SharedVector<slint::cbindgen_private::Value *> *>(
|
||||
&array))) {
|
||||
return array;
|
||||
} else {
|
||||
return {};
|
||||
|
@ -470,18 +459,21 @@ inline Value::Value(const std::shared_ptr<slint::Model<Value>> &model)
|
|||
auto row_count = [](VRef<ModelAdaptorVTable> self) -> uintptr_t {
|
||||
return reinterpret_cast<ModelWrapper *>(self.instance)->model->row_count();
|
||||
};
|
||||
auto row_data = [](VRef<ModelAdaptorVTable> self, uintptr_t row, ValueOpaque *out) {
|
||||
auto row_data = [](VRef<ModelAdaptorVTable> self,
|
||||
uintptr_t row) -> slint::cbindgen_private::Value * {
|
||||
std::optional<Value> v =
|
||||
reinterpret_cast<ModelWrapper *>(self.instance)->model->row_data(int(row));
|
||||
if (v.has_value()) {
|
||||
*out = v->inner;
|
||||
cbindgen_private::slint_interpreter_value_new(&v->inner);
|
||||
return true;
|
||||
slint::cbindgen_private::Value *rval = v->inner;
|
||||
v->inner = cbindgen_private::slint_interpreter_value_new();
|
||||
return rval;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
auto set_row_data = [](VRef<ModelAdaptorVTable> self, uintptr_t row, const ValueOpaque *value) {
|
||||
Value v = *reinterpret_cast<const Value *>(value);
|
||||
auto set_row_data = [](VRef<ModelAdaptorVTable> self, uintptr_t row,
|
||||
slint::cbindgen_private::Value *value) {
|
||||
Value v(std::move(value));
|
||||
reinterpret_cast<ModelWrapper *>(self.instance)->model->set_row_data(int(row), v);
|
||||
};
|
||||
auto get_notify =
|
||||
|
@ -493,8 +485,8 @@ inline Value::Value(const std::shared_ptr<slint::Model<Value>> &model)
|
|||
};
|
||||
|
||||
static const ModelAdaptorVTable vt { row_count, row_data, set_row_data, get_notify, drop };
|
||||
cbindgen_private::slint_interpreter_value_new_model(reinterpret_cast<uint8_t *>(wrapper.get()),
|
||||
&vt, &inner);
|
||||
inner = cbindgen_private::slint_interpreter_value_new_model(
|
||||
reinterpret_cast<uint8_t *>(wrapper.get()), &vt);
|
||||
}
|
||||
|
||||
inline Struct::Struct(std::initializer_list<std::pair<std::string_view, Value>> args)
|
||||
|
@ -504,12 +496,14 @@ inline Struct::Struct(std::initializer_list<std::pair<std::string_view, Value>>
|
|||
|
||||
inline std::optional<Value> Struct::get_field(std::string_view name) const
|
||||
{
|
||||
using namespace cbindgen_private;
|
||||
cbindgen_private::Slice<uint8_t> name_view {
|
||||
const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(name.data())),
|
||||
name.size()
|
||||
};
|
||||
if (auto *value = cbindgen_private::slint_interpreter_struct_get_field(&inner, name_view)) {
|
||||
return *reinterpret_cast<const Value *>(value);
|
||||
if (cbindgen_private::Value *field_val =
|
||||
cbindgen_private::slint_interpreter_struct_get_field(&inner, name_view)) {
|
||||
return Value(std::move(field_val));
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
|
@ -520,7 +514,32 @@ inline void Struct::set_field(std::string_view name, const Value &value)
|
|||
const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(name.data())),
|
||||
name.size()
|
||||
};
|
||||
cbindgen_private::slint_interpreter_struct_set_field(&inner, name_view, &value.inner);
|
||||
cbindgen_private::slint_interpreter_struct_set_field(&inner, name_view, value.inner);
|
||||
}
|
||||
|
||||
inline void Struct::iterator::next()
|
||||
{
|
||||
cbindgen_private::Slice<uint8_t> name_slice;
|
||||
|
||||
if (cbindgen_private::Value *nextval_inner =
|
||||
cbindgen_private::slint_interpreter_struct_iterator_next(&inner, &name_slice)) {
|
||||
k = std::string_view(reinterpret_cast<char *>(name_slice.ptr), name_slice.len);
|
||||
if (!v)
|
||||
v = new Value();
|
||||
*v = Value(std::move(nextval_inner));
|
||||
} else {
|
||||
cbindgen_private::slint_interpreter_struct_iterator_destructor(&inner);
|
||||
delete v;
|
||||
v = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline Struct::iterator::~iterator()
|
||||
{
|
||||
if (v) {
|
||||
cbindgen_private::slint_interpreter_struct_iterator_destructor(&inner);
|
||||
delete v;
|
||||
}
|
||||
}
|
||||
|
||||
/// The ComponentInstance represents a running instance of a component.
|
||||
|
@ -606,16 +625,15 @@ public:
|
|||
{
|
||||
using namespace cbindgen_private;
|
||||
return slint_interpreter_component_instance_set_property(
|
||||
inner(), slint::private_api::string_to_slice(name), &value.inner);
|
||||
inner(), slint::private_api::string_to_slice(name), value.inner);
|
||||
}
|
||||
/// Returns the value behind a property declared in .slint.
|
||||
std::optional<Value> get_property(std::string_view name) const
|
||||
{
|
||||
using namespace cbindgen_private;
|
||||
ValueOpaque out;
|
||||
if (slint_interpreter_component_instance_get_property(
|
||||
inner(), slint::private_api::string_to_slice(name), &out)) {
|
||||
return Value(out);
|
||||
if (cbindgen_private::Value *prop_inner = slint_interpreter_component_instance_get_property(
|
||||
inner(), slint::private_api::string_to_slice(name))) {
|
||||
return Value(std::move(prop_inner));
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
|
@ -638,13 +656,14 @@ public:
|
|||
std::optional<Value> invoke(std::string_view name, std::span<const Value> args) const
|
||||
{
|
||||
using namespace cbindgen_private;
|
||||
Slice<ValueOpaque> args_view { const_cast<ValueOpaque *>(
|
||||
reinterpret_cast<const ValueOpaque *>(args.data())),
|
||||
args.size() };
|
||||
ValueOpaque out;
|
||||
if (slint_interpreter_component_instance_invoke(
|
||||
inner(), slint::private_api::string_to_slice(name), args_view, &out)) {
|
||||
return Value(out);
|
||||
Slice<Box<cbindgen_private::Value>> args_view {
|
||||
const_cast<Box<cbindgen_private::Value> *>(
|
||||
reinterpret_cast<const Box<cbindgen_private::Value> *>(args.data())),
|
||||
args.size()
|
||||
};
|
||||
if (cbindgen_private::Value *rval_inner = slint_interpreter_component_instance_invoke(
|
||||
inner(), slint::private_api::string_to_slice(name), args_view)) {
|
||||
return Value(std::move(rval_inner));
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
|
@ -677,12 +696,15 @@ public:
|
|||
auto set_callback(std::string_view name, F callback) const -> bool
|
||||
// clang-format on
|
||||
{
|
||||
using cbindgen_private::ValueOpaque;
|
||||
auto actual_cb = [](void *data, cbindgen_private::Slice<ValueOpaque> arg,
|
||||
ValueOpaque *ret) {
|
||||
using namespace cbindgen_private;
|
||||
auto actual_cb = [](void *data,
|
||||
cbindgen_private::Slice<cbindgen_private::Box<cbindgen_private::Value>>
|
||||
arg) {
|
||||
std::span<const Value> args_view { reinterpret_cast<const Value *>(arg.ptr), arg.len };
|
||||
Value r = (*reinterpret_cast<F *>(data))(args_view);
|
||||
new (ret) Value(std::move(r));
|
||||
auto inner = r.inner;
|
||||
r.inner = cbindgen_private::slint_interpreter_value_new();
|
||||
return inner;
|
||||
};
|
||||
return cbindgen_private::slint_interpreter_component_instance_set_callback(
|
||||
inner(), slint::private_api::string_to_slice(name), actual_cb,
|
||||
|
@ -709,18 +731,18 @@ public:
|
|||
using namespace cbindgen_private;
|
||||
return slint_interpreter_component_instance_set_global_property(
|
||||
inner(), slint::private_api::string_to_slice(global),
|
||||
slint::private_api::string_to_slice(prop_name), &value.inner);
|
||||
slint::private_api::string_to_slice(prop_name), value.inner);
|
||||
}
|
||||
/// Returns the value behind a property in an exported global singleton.
|
||||
std::optional<Value> get_global_property(std::string_view global,
|
||||
std::string_view prop_name) const
|
||||
{
|
||||
using namespace cbindgen_private;
|
||||
ValueOpaque out;
|
||||
if (slint_interpreter_component_instance_get_global_property(
|
||||
inner(), slint::private_api::string_to_slice(global),
|
||||
slint::private_api::string_to_slice(prop_name), &out)) {
|
||||
return Value(out);
|
||||
if (cbindgen_private::Value *rval_inner =
|
||||
slint_interpreter_component_instance_get_global_property(
|
||||
inner(), slint::private_api::string_to_slice(global),
|
||||
slint::private_api::string_to_slice(prop_name))) {
|
||||
return Value(std::move(rval_inner));
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
|
@ -748,12 +770,15 @@ public:
|
|||
template<std::invocable<std::span<const Value>> F>
|
||||
bool set_global_callback(std::string_view global, std::string_view name, F callback) const
|
||||
{
|
||||
using cbindgen_private::ValueOpaque;
|
||||
auto actual_cb = [](void *data, cbindgen_private::Slice<ValueOpaque> arg,
|
||||
ValueOpaque *ret) {
|
||||
using namespace cbindgen_private;
|
||||
auto actual_cb = [](void *data,
|
||||
cbindgen_private::Slice<cbindgen_private::Box<cbindgen_private::Value>>
|
||||
arg) {
|
||||
std::span<const Value> args_view { reinterpret_cast<const Value *>(arg.ptr), arg.len };
|
||||
Value r = (*reinterpret_cast<F *>(data))(args_view);
|
||||
new (ret) Value(std::move(r));
|
||||
auto inner = r.inner;
|
||||
r.inner = cbindgen_private::slint_interpreter_value_new();
|
||||
return inner;
|
||||
};
|
||||
return cbindgen_private::slint_interpreter_component_instance_set_global_callback(
|
||||
inner(), slint::private_api::string_to_slice(global),
|
||||
|
@ -766,14 +791,17 @@ public:
|
|||
std::span<const Value> args) const
|
||||
{
|
||||
using namespace cbindgen_private;
|
||||
Slice<ValueOpaque> args_view { const_cast<ValueOpaque *>(
|
||||
reinterpret_cast<const ValueOpaque *>(args.data())),
|
||||
args.size() };
|
||||
ValueOpaque out;
|
||||
if (slint_interpreter_component_instance_invoke_global(
|
||||
inner(), slint::private_api::string_to_slice(global),
|
||||
slint::private_api::string_to_slice(callable_name), args_view, &out)) {
|
||||
return Value(out);
|
||||
Slice<cbindgen_private::Box<cbindgen_private::Value>> args_view {
|
||||
const_cast<cbindgen_private::Box<cbindgen_private::Value> *>(
|
||||
reinterpret_cast<const cbindgen_private::Box<cbindgen_private::Value> *>(
|
||||
args.data())),
|
||||
args.size()
|
||||
};
|
||||
if (cbindgen_private::Value *rval_inner =
|
||||
slint_interpreter_component_instance_invoke_global(
|
||||
inner(), slint::private_api::string_to_slice(global),
|
||||
slint::private_api::string_to_slice(callable_name), args_view)) {
|
||||
return Value(std::move(rval_inner));
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
|
@ -1001,7 +1029,6 @@ public:
|
|||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace slint::testing {
|
||||
|
|
|
@ -11,101 +11,72 @@ use i_slint_core::window::WindowAdapter;
|
|||
use std::ffi::c_void;
|
||||
use vtable::VRef;
|
||||
|
||||
#[repr(C)]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub struct ValueOpaque([usize; 7]);
|
||||
#[repr(C)]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[repr(align(8))]
|
||||
pub struct ValueOpaque([usize; 9]);
|
||||
/// Asserts that ValueOpaque is as large as Value and has the same alignment, to make transmute safe.
|
||||
const _: [(); std::mem::size_of::<ValueOpaque>()] = [(); std::mem::size_of::<Value>()];
|
||||
const _: [(); std::mem::align_of::<ValueOpaque>()] = [(); std::mem::align_of::<Value>()];
|
||||
|
||||
impl ValueOpaque {
|
||||
fn as_value(&self) -> &Value {
|
||||
// Safety: there should be no way to construct a ValueOpaque without it holding an actual Value
|
||||
unsafe { std::mem::transmute::<&ValueOpaque, &Value>(self) }
|
||||
}
|
||||
/// Construct a new Value in the given memory location
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new() -> Box<Value> {
|
||||
Box::new(Value::default())
|
||||
}
|
||||
|
||||
/// Construct a new Value in the given memory location
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new(val: *mut ValueOpaque) {
|
||||
std::ptr::write(val as *mut Value, Value::default())
|
||||
}
|
||||
|
||||
/// Construct a new Value in the given memory location
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_clone(other: &ValueOpaque, val: *mut ValueOpaque) {
|
||||
std::ptr::write(val as *mut Value, other.as_value().clone())
|
||||
pub unsafe extern "C" fn slint_interpreter_value_clone(other: &Value) -> Box<Value> {
|
||||
Box::new(other.clone())
|
||||
}
|
||||
|
||||
/// Destruct the value in that memory location
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_destructor(val: *mut ValueOpaque) {
|
||||
drop(std::ptr::read(val as *mut Value))
|
||||
pub unsafe extern "C" fn slint_interpreter_value_destructor(val: Box<Value>) {
|
||||
drop(val);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_interpreter_value_eq(a: &ValueOpaque, b: &ValueOpaque) -> bool {
|
||||
a.as_value() == b.as_value()
|
||||
pub extern "C" fn slint_interpreter_value_eq(a: &Value, b: &Value) -> bool {
|
||||
a == b
|
||||
}
|
||||
|
||||
/// Construct a new Value in the given memory location as string
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_string(
|
||||
str: &SharedString,
|
||||
val: *mut ValueOpaque,
|
||||
) {
|
||||
std::ptr::write(val as *mut Value, Value::String(str.clone()))
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_string(str: &SharedString) -> Box<Value> {
|
||||
Box::new(Value::String(str.clone()))
|
||||
}
|
||||
|
||||
/// Construct a new Value in the given memory location as double
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_double(double: f64, val: *mut ValueOpaque) {
|
||||
std::ptr::write(val as *mut Value, Value::Number(double))
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_double(double: f64) -> Box<Value> {
|
||||
Box::new(Value::Number(double))
|
||||
}
|
||||
|
||||
/// Construct a new Value in the given memory location as bool
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_bool(b: bool, val: *mut ValueOpaque) {
|
||||
std::ptr::write(val as *mut Value, Value::Bool(b))
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_bool(b: bool) -> Box<Value> {
|
||||
Box::new(Value::Bool(b))
|
||||
}
|
||||
|
||||
/// Construct a new Value in the given memory location as array model
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_array_model(
|
||||
a: &SharedVector<ValueOpaque>,
|
||||
val: *mut ValueOpaque,
|
||||
) {
|
||||
// Safety: We assert that Value and ValueOpaque have the same size and alignment
|
||||
let vec = std::mem::transmute::<SharedVector<ValueOpaque>, SharedVector<Value>>(a.clone());
|
||||
std::ptr::write(
|
||||
val as *mut Value,
|
||||
Value::Model(ModelRc::new(SharedVectorModel::<Value>::from(vec))),
|
||||
)
|
||||
a: &SharedVector<Box<Value>>,
|
||||
) -> Box<Value> {
|
||||
let vec = a.iter().map(|vb| vb.as_ref().clone()).collect::<SharedVector<_>>();
|
||||
Box::new(Value::Model(ModelRc::new(SharedVectorModel::from(vec))))
|
||||
}
|
||||
|
||||
/// Construct a new Value in the given memory location as Brush
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_brush(brush: &Brush, val: *mut ValueOpaque) {
|
||||
std::ptr::write(val as *mut Value, Value::Brush(brush.clone()))
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_brush(brush: &Brush) -> Box<Value> {
|
||||
Box::new(Value::Brush(brush.clone()))
|
||||
}
|
||||
|
||||
/// Construct a new Value in the given memory location as Struct
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_struct(
|
||||
struc: &StructOpaque,
|
||||
val: *mut ValueOpaque,
|
||||
) {
|
||||
std::ptr::write(val as *mut Value, Value::Struct(struc.as_struct().clone()))
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_struct(struc: &StructOpaque) -> Box<Value> {
|
||||
Box::new(Value::Struct(struc.as_struct().clone()))
|
||||
}
|
||||
|
||||
/// Construct a new Value in the given memory location as image
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_image(img: &Image, val: *mut ValueOpaque) {
|
||||
std::ptr::write(val as *mut Value, Value::Image(img.clone()))
|
||||
pub unsafe extern "C" fn slint_interpreter_value_new_image(img: &Image) -> Box<Value> {
|
||||
Box::new(Value::Image(img.clone()))
|
||||
}
|
||||
|
||||
/// Construct a new Value containing a model in the given memory location
|
||||
|
@ -113,41 +84,37 @@ pub unsafe extern "C" fn slint_interpreter_value_new_image(img: &Image, val: *mu
|
|||
pub unsafe extern "C" fn slint_interpreter_value_new_model(
|
||||
model: NonNull<u8>,
|
||||
vtable: &ModelAdaptorVTable,
|
||||
val: *mut ValueOpaque,
|
||||
) {
|
||||
std::ptr::write(
|
||||
val as *mut Value,
|
||||
Value::Model(ModelRc::new(ModelAdaptorWrapper(vtable::VBox::from_raw(
|
||||
NonNull::from(vtable),
|
||||
model,
|
||||
)))),
|
||||
)
|
||||
) -> Box<Value> {
|
||||
Box::new(Value::Model(ModelRc::new(ModelAdaptorWrapper(vtable::VBox::from_raw(
|
||||
NonNull::from(vtable),
|
||||
model,
|
||||
)))))
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_value_type(val: *const ValueOpaque) -> ValueType {
|
||||
(&*val).as_value().value_type()
|
||||
pub unsafe extern "C" fn slint_interpreter_value_type(val: &Value) -> ValueType {
|
||||
val.value_type()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_interpreter_value_to_string(val: &ValueOpaque) -> Option<&SharedString> {
|
||||
match val.as_value() {
|
||||
pub extern "C" fn slint_interpreter_value_to_string(val: &Value) -> Option<&SharedString> {
|
||||
match val {
|
||||
Value::String(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_interpreter_value_to_number(val: &ValueOpaque) -> Option<&f64> {
|
||||
match val.as_value() {
|
||||
pub extern "C" fn slint_interpreter_value_to_number(val: &Value) -> Option<&f64> {
|
||||
match val {
|
||||
Value::Number(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_interpreter_value_to_bool(val: &ValueOpaque) -> Option<&bool> {
|
||||
match val.as_value() {
|
||||
pub extern "C" fn slint_interpreter_value_to_bool(val: &Value) -> Option<&bool> {
|
||||
match val {
|
||||
Value::Bool(v) => Some(v),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -158,23 +125,14 @@ pub extern "C" fn slint_interpreter_value_to_bool(val: &ValueOpaque) -> Option<&
|
|||
/// array.
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_interpreter_value_to_array(
|
||||
val: &ValueOpaque,
|
||||
out: *mut SharedVector<ValueOpaque>,
|
||||
val: &Box<Value>,
|
||||
out: *mut SharedVector<Box<Value>>,
|
||||
) -> bool {
|
||||
match val.as_value() {
|
||||
match val.as_ref() {
|
||||
Value::Model(m) => {
|
||||
let vec = if let Some(model) = m.as_any().downcast_ref::<SharedVectorModel<Value>>() {
|
||||
model.shared_vector()
|
||||
} else {
|
||||
m.iter().collect()
|
||||
};
|
||||
|
||||
// Safety: We assert that Value and ValueOpaque have the same size and alignment
|
||||
let vec = m.iter().map(|vb| Box::new(vb)).collect::<SharedVector<_>>();
|
||||
unsafe {
|
||||
std::ptr::write(
|
||||
out,
|
||||
std::mem::transmute::<SharedVector<Value>, SharedVector<ValueOpaque>>(vec),
|
||||
);
|
||||
std::ptr::write(out, vec);
|
||||
}
|
||||
|
||||
true
|
||||
|
@ -184,24 +142,24 @@ pub extern "C" fn slint_interpreter_value_to_array(
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_interpreter_value_to_brush(val: &ValueOpaque) -> Option<&Brush> {
|
||||
match val.as_value() {
|
||||
pub extern "C" fn slint_interpreter_value_to_brush(val: &Value) -> Option<&Brush> {
|
||||
match val {
|
||||
Value::Brush(b) => Some(b),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_interpreter_value_to_struct(val: &ValueOpaque) -> *const StructOpaque {
|
||||
match val.as_value() {
|
||||
pub extern "C" fn slint_interpreter_value_to_struct(val: &Value) -> *const StructOpaque {
|
||||
match val {
|
||||
Value::Struct(s) => s as *const Struct as *const StructOpaque,
|
||||
_ => std::ptr::null(),
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_interpreter_value_to_image(val: &ValueOpaque) -> Option<&Image> {
|
||||
match val.as_value() {
|
||||
pub extern "C" fn slint_interpreter_value_to_image(val: &Value) -> Option<&Image> {
|
||||
match val {
|
||||
Value::Image(img) => Some(img),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -249,23 +207,24 @@ pub unsafe extern "C" fn slint_interpreter_struct_destructor(val: *mut StructOpa
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_interpreter_struct_get_field<'a>(
|
||||
stru: &'a StructOpaque,
|
||||
pub extern "C" fn slint_interpreter_struct_get_field(
|
||||
stru: &StructOpaque,
|
||||
name: Slice<u8>,
|
||||
) -> Option<&'a ValueOpaque> {
|
||||
stru.as_struct()
|
||||
.get_field(std::str::from_utf8(&name).unwrap())
|
||||
.and_then(|v| unsafe { (v as *const Value as *const ValueOpaque).as_ref() })
|
||||
) -> *mut Value {
|
||||
if let Some(value) = stru.as_struct().get_field(std::str::from_utf8(&name).unwrap()) {
|
||||
Box::into_raw(Box::new(value.clone()))
|
||||
} else {
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn slint_interpreter_struct_set_field<'a>(
|
||||
stru: &'a mut StructOpaque,
|
||||
name: Slice<u8>,
|
||||
value: &ValueOpaque,
|
||||
value: &Value,
|
||||
) {
|
||||
stru.as_struct_mut()
|
||||
.set_field(std::str::from_utf8(&name).unwrap().into(), value.as_value().clone())
|
||||
stru.as_struct_mut().set_field(std::str::from_utf8(&name).unwrap().into(), value.clone())
|
||||
}
|
||||
|
||||
type StructIterator<'a> = std::collections::hash_map::Iter<'a, String, Value>;
|
||||
|
@ -283,23 +242,18 @@ pub unsafe extern "C" fn slint_interpreter_struct_iterator_destructor(
|
|||
drop(std::ptr::read(val as *mut StructIterator))
|
||||
}
|
||||
|
||||
/// The result of the slint_interpreter_struct_iterator_next function
|
||||
/// If the iterator was at the end, the key will be empty, and the value will be None
|
||||
#[repr(C)]
|
||||
pub struct StructIteratorResult<'a> {
|
||||
k: Slice<'a, u8>,
|
||||
v: Option<&'a Value>,
|
||||
}
|
||||
|
||||
/// Advance the iterator and return the next value, or an
|
||||
/// Advance the iterator and return the next value, or a null pointer
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_struct_iterator_next<'a>(
|
||||
iter: &'a mut StructIteratorOpaque,
|
||||
) -> StructIteratorResult<'a> {
|
||||
k: &mut Slice<'a, u8>,
|
||||
) -> *mut Value {
|
||||
if let Some((str, val)) = (*(iter as *mut StructIteratorOpaque as *mut StructIterator)).next() {
|
||||
StructIteratorResult { k: Slice::from_slice(str.as_bytes()), v: Some(val) }
|
||||
*k = Slice::from_slice(str.as_bytes());
|
||||
Box::into_raw(Box::new(val.clone()))
|
||||
} else {
|
||||
StructIteratorResult { k: Slice::default(), v: None }
|
||||
*k = Slice::default();
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -313,26 +267,20 @@ pub extern "C" fn slint_interpreter_struct_make_iter(stru: &StructOpaque) -> Str
|
|||
}
|
||||
}
|
||||
|
||||
/// Get a property.
|
||||
/// The `out` parameter must be uninitialized. If this function returns true, the out will be initialized
|
||||
/// to the resulting value. If this function returns false, out is unchanged
|
||||
/// Get a property. Returns a null pointer if the property does not exist.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_component_instance_get_property(
|
||||
inst: &ErasedItemTreeBox,
|
||||
name: Slice<u8>,
|
||||
out: *mut ValueOpaque,
|
||||
) -> bool {
|
||||
) -> *mut Value {
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
match comp
|
||||
.description()
|
||||
.get_property(comp.borrow(), &normalize_identifier(std::str::from_utf8(&name).unwrap()))
|
||||
{
|
||||
Ok(val) => {
|
||||
std::ptr::write(out as *mut Value, val);
|
||||
true
|
||||
}
|
||||
Err(_) => false,
|
||||
Ok(val) => Box::into_raw(Box::new(val)),
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,7 +288,7 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_get_property(
|
|||
pub extern "C" fn slint_interpreter_component_instance_set_property(
|
||||
inst: &ErasedItemTreeBox,
|
||||
name: Slice<u8>,
|
||||
val: &ValueOpaque,
|
||||
val: &Value,
|
||||
) -> bool {
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
|
@ -348,22 +296,19 @@ pub extern "C" fn slint_interpreter_component_instance_set_property(
|
|||
.set_property(
|
||||
comp.borrow(),
|
||||
&normalize_identifier(std::str::from_utf8(&name).unwrap()),
|
||||
val.as_value().clone(),
|
||||
val.clone(),
|
||||
)
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
/// Invoke a callback or function
|
||||
/// The `out` parameter must be uninitialized. If this function returns true, the out will be initialized
|
||||
/// to the resulting value. If this function returns false, out is unchanged
|
||||
/// Invoke a callback or function. Returns raw boxed value on success and null ptr on failure.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_component_instance_invoke(
|
||||
inst: &ErasedItemTreeBox,
|
||||
name: Slice<u8>,
|
||||
args: Slice<ValueOpaque>,
|
||||
out: *mut ValueOpaque,
|
||||
) -> bool {
|
||||
let args = std::mem::transmute::<Slice<ValueOpaque>, Slice<Value>>(args);
|
||||
args: Slice<Box<Value>>,
|
||||
) -> *mut Value {
|
||||
let args = args.iter().map(|vb| vb.as_ref().clone()).collect::<Vec<_>>();
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
match comp.description().invoke(
|
||||
|
@ -371,11 +316,8 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_invoke(
|
|||
&normalize_identifier(std::str::from_utf8(&name).unwrap()),
|
||||
args.as_slice(),
|
||||
) {
|
||||
Ok(val) => {
|
||||
std::ptr::write(out as *mut Value, val);
|
||||
true
|
||||
}
|
||||
Err(_) => false,
|
||||
Ok(val) => Box::into_raw(Box::new(val)),
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -386,7 +328,7 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_invoke(
|
|||
struct CallbackUserData {
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
callback: extern "C" fn(user_data: *mut c_void, arg: Slice<ValueOpaque>, ret: *mut ValueOpaque),
|
||||
callback: extern "C" fn(user_data: *mut c_void, arg: Slice<Box<Value>>) -> Box<Value>,
|
||||
}
|
||||
|
||||
impl Drop for CallbackUserData {
|
||||
|
@ -399,16 +341,8 @@ impl Drop for CallbackUserData {
|
|||
|
||||
impl CallbackUserData {
|
||||
fn call(&self, args: &[Value]) -> Value {
|
||||
unsafe {
|
||||
let args = std::mem::transmute::<&[Value], &[ValueOpaque]>(args);
|
||||
let mut ret = std::mem::MaybeUninit::<Value>::uninit();
|
||||
(self.callback)(
|
||||
self.user_data,
|
||||
Slice::from_slice(args),
|
||||
ret.as_mut_ptr() as *mut ValueOpaque,
|
||||
);
|
||||
ret.assume_init()
|
||||
}
|
||||
let args = args.iter().map(|v| v.clone().into()).collect::<Vec<_>>();
|
||||
(self.callback)(self.user_data, Slice::from_slice(args.as_ref())).as_ref().clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,7 +352,7 @@ impl CallbackUserData {
|
|||
pub unsafe extern "C" fn slint_interpreter_component_instance_set_callback(
|
||||
inst: &ErasedItemTreeBox,
|
||||
name: Slice<u8>,
|
||||
callback: extern "C" fn(user_data: *mut c_void, arg: Slice<ValueOpaque>, ret: *mut ValueOpaque),
|
||||
callback: extern "C" fn(user_data: *mut c_void, arg: Slice<Box<Value>>) -> Box<Value>,
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
) -> bool {
|
||||
|
@ -435,16 +369,13 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_set_callback(
|
|||
.is_ok()
|
||||
}
|
||||
|
||||
/// Get a global property.
|
||||
/// The `out` parameter must be uninitialized. If this function returns true, the out will be initialized
|
||||
/// to the resulting value. If this function returns false, out is unchanged
|
||||
/// Get a global property. Returns a raw boxed value on success; nullptr otherwise.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_component_instance_get_global_property(
|
||||
inst: &ErasedItemTreeBox,
|
||||
global: Slice<u8>,
|
||||
property_name: Slice<u8>,
|
||||
out: *mut ValueOpaque,
|
||||
) -> bool {
|
||||
) -> *mut Value {
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
match comp
|
||||
|
@ -454,11 +385,8 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_get_global_propert
|
|||
g.as_ref()
|
||||
.get_property(&normalize_identifier(std::str::from_utf8(&property_name).unwrap()))
|
||||
}) {
|
||||
Ok(val) => {
|
||||
std::ptr::write(out as *mut Value, val);
|
||||
true
|
||||
}
|
||||
Err(_) => false,
|
||||
Ok(val) => Box::into_raw(Box::new(val)),
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,7 +395,7 @@ pub extern "C" fn slint_interpreter_component_instance_set_global_property(
|
|||
inst: &ErasedItemTreeBox,
|
||||
global: Slice<u8>,
|
||||
property_name: Slice<u8>,
|
||||
val: &ValueOpaque,
|
||||
val: &Value,
|
||||
) -> bool {
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
|
@ -477,7 +405,7 @@ pub extern "C" fn slint_interpreter_component_instance_set_global_property(
|
|||
g.as_ref()
|
||||
.set_property(
|
||||
&normalize_identifier(std::str::from_utf8(&property_name).unwrap()),
|
||||
val.as_value().clone(),
|
||||
val.clone(),
|
||||
)
|
||||
.map_err(|_| ())
|
||||
})
|
||||
|
@ -490,7 +418,7 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_set_global_callbac
|
|||
inst: &ErasedItemTreeBox,
|
||||
global: Slice<u8>,
|
||||
name: Slice<u8>,
|
||||
callback: extern "C" fn(user_data: *mut c_void, arg: Slice<ValueOpaque>, ret: *mut ValueOpaque),
|
||||
callback: extern "C" fn(user_data: *mut c_void, arg: Slice<Box<Value>>) -> Box<Value>,
|
||||
user_data: *mut c_void,
|
||||
drop_user_data: Option<extern "C" fn(*mut c_void)>,
|
||||
) -> bool {
|
||||
|
@ -509,18 +437,15 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_set_global_callbac
|
|||
.is_ok()
|
||||
}
|
||||
|
||||
/// Invoke a global callback or function.
|
||||
/// The `out` parameter must be uninitialized. If this function returns true, the out will be initialized
|
||||
/// to the resulting value. If this function returns false, out is unchanged
|
||||
/// Invoke a global callback or function. Returns raw boxed value on success; nullptr otherwise.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn slint_interpreter_component_instance_invoke_global(
|
||||
inst: &ErasedItemTreeBox,
|
||||
global: Slice<u8>,
|
||||
callable_name: Slice<u8>,
|
||||
args: Slice<ValueOpaque>,
|
||||
out: *mut ValueOpaque,
|
||||
) -> bool {
|
||||
let args = std::mem::transmute::<Slice<ValueOpaque>, Slice<Value>>(args);
|
||||
args: Slice<Box<Value>>,
|
||||
) -> *mut Value {
|
||||
let args = args.iter().map(|vb| vb.as_ref().clone()).collect::<Vec<_>>();
|
||||
generativity::make_guard!(guard);
|
||||
let comp = inst.unerase(guard);
|
||||
let callable_name = std::str::from_utf8(&callable_name).unwrap();
|
||||
|
@ -545,11 +470,8 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_invoke_global(
|
|||
g.as_ref().invoke_callback(&normalize_identifier(callable_name), args.as_slice())
|
||||
}
|
||||
}) {
|
||||
Ok(val) => {
|
||||
std::ptr::write(out as *mut Value, val);
|
||||
true
|
||||
}
|
||||
Err(_) => false,
|
||||
Ok(val) => Box::into_raw(Box::new(val)),
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -602,9 +524,8 @@ pub unsafe extern "C" fn slint_interpreter_component_instance_create(
|
|||
#[repr(C)]
|
||||
pub struct ModelAdaptorVTable {
|
||||
pub row_count: extern "C" fn(VRef<ModelAdaptorVTable>) -> usize,
|
||||
pub row_data:
|
||||
unsafe extern "C" fn(VRef<ModelAdaptorVTable>, row: usize, out: *mut ValueOpaque) -> bool,
|
||||
pub set_row_data: extern "C" fn(VRef<ModelAdaptorVTable>, row: usize, value: &ValueOpaque),
|
||||
pub row_data: unsafe extern "C" fn(VRef<ModelAdaptorVTable>, row: usize) -> *mut Value,
|
||||
pub set_row_data: extern "C" fn(VRef<ModelAdaptorVTable>, row: usize, value: Box<Value>),
|
||||
pub get_notify: extern "C" fn(VRef<ModelAdaptorVTable>) -> &ModelNotifyOpaque,
|
||||
pub drop: extern "C" fn(VRefMut<ModelAdaptorVTable>),
|
||||
}
|
||||
|
@ -618,13 +539,11 @@ impl Model for ModelAdaptorWrapper {
|
|||
}
|
||||
|
||||
fn row_data(&self, row: usize) -> Option<Value> {
|
||||
unsafe {
|
||||
let mut v = std::mem::MaybeUninit::<Value>::uninit();
|
||||
if self.0.row_data(row, v.as_mut_ptr() as *mut ValueOpaque) {
|
||||
Some(v.assume_init())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
let val_ptr = unsafe { self.0.row_data(row) };
|
||||
if val_ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(*unsafe { Box::from_raw(val_ptr) })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,7 +552,7 @@ impl Model for ModelAdaptorWrapper {
|
|||
}
|
||||
|
||||
fn set_row_data(&self, row: usize, data: Value) {
|
||||
let val: &ValueOpaque = unsafe { std::mem::transmute::<&Value, &ValueOpaque>(&data) };
|
||||
let val = Box::new(data);
|
||||
self.0.set_row_data(row, val);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue