Generate the rust code.
parent
ff2a0a1f70
commit
91962f3f2b
|
@ -8,4 +8,3 @@ libc = "*"
|
|||
[lib]
|
||||
name = "rust"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
|
|
|
@ -46,12 +46,12 @@ impl DirEntry {
|
|||
}
|
||||
|
||||
impl Item for DirEntry {
|
||||
fn data<'a>(&self, role: c_int) -> Variant<'a> {
|
||||
fn data(&self, role: c_int) -> Variant {
|
||||
if role != 0 {
|
||||
return Variant::None
|
||||
}
|
||||
let str = self.name.to_string_lossy().to_string();
|
||||
return Variant::from(str);
|
||||
Variant::from(str)
|
||||
}
|
||||
fn retrieve(&self, parents: Vec<&DirEntry>) -> Vec<DirEntry> {
|
||||
let path: PathBuf = parents.into_iter().map(|e|&e.name).collect();
|
||||
|
@ -65,7 +65,7 @@ impl Item for DirEntry {
|
|||
}
|
||||
}
|
||||
v.sort_by(|a, b| a.name.cmp(&b.name));
|
||||
return v;
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ impl Default for DirEntry {
|
|||
|
||||
pub trait Item: Default {
|
||||
fn retrieve(&self, parents: Vec<&Self>) -> Vec<Self>;
|
||||
fn data<'a>(&self, role: c_int) -> Variant<'a>;
|
||||
fn data(&self, role: c_int) -> Variant;
|
||||
}
|
||||
|
||||
pub type RItemModel = RGeneralItemModel<DirEntry>;
|
||||
|
@ -117,10 +117,9 @@ impl<T: Item> RGeneralItemModel<T> {
|
|||
let mut new_entries = Vec::new();
|
||||
let mut children = Vec::new();
|
||||
{
|
||||
let mut row = 0;
|
||||
let parents = self.get_parents(id);
|
||||
let entries = self.entries[id].data.retrieve(parents);
|
||||
for d in entries {
|
||||
for (row, d) in entries.into_iter().enumerate() {
|
||||
let e = Entry {
|
||||
parent: id,
|
||||
row: row,
|
||||
|
@ -128,7 +127,6 @@ impl<T: Item> RGeneralItemModel<T> {
|
|||
data: d
|
||||
};
|
||||
children.push(self.entries.len() + row);
|
||||
row += 1;
|
||||
new_entries.push(e);
|
||||
}
|
||||
}
|
||||
|
@ -172,11 +170,11 @@ impl<T: Item> RItemModelTrait<T> for RGeneralItemModel<T> {
|
|||
if !index.is_valid() || index.id() == 1 {
|
||||
return QModelIndex::invalid();
|
||||
}
|
||||
let ref e = self.entries[index.id()];
|
||||
let e = &self.entries[index.id()];
|
||||
QModelIndex::create(e.row as i32, 0, e.parent)
|
||||
}
|
||||
fn data<'a>(&'a mut self, index: QModelIndex, role: c_int) -> Variant<'a> {
|
||||
fn data(&mut self, index: QModelIndex, role: c_int) -> Variant {
|
||||
let i = self.get(&index);
|
||||
return self.entries[i].data.data(role);
|
||||
self.entries[i].data.data(role)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(unknown_lints)]
|
||||
#![allow(mutex_atomic)]
|
||||
use std::slice;
|
||||
use libc::{c_int, uint16_t, size_t, c_void};
|
||||
use types::*;
|
||||
|
@ -36,23 +38,20 @@ pub extern fn hello_new(qobject: *const HelloQObject, changed: fn(*const HelloQO
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn hello_free(ptr: *mut Hello) {
|
||||
pub unsafe extern fn hello_free(ptr: *mut Hello) {
|
||||
if ptr.is_null() { return }
|
||||
unsafe { Box::from_raw(ptr); }
|
||||
Box::from_raw(ptr);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn hello_set(ptr: *mut Hello, s: *const uint16_t, len: size_t) {
|
||||
let (hello, data) = unsafe {
|
||||
(&mut *ptr, slice::from_raw_parts(s, len as usize))
|
||||
};
|
||||
hello.set_hello(String::from_utf16_lossy(data));
|
||||
pub unsafe extern fn hello_set(ptr: *mut Hello, s: *const uint16_t, len: size_t) {
|
||||
let data = slice::from_raw_parts(s, len as usize);
|
||||
(&mut *ptr).set_hello(String::from_utf16_lossy(data));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn hello_get(ptr: *mut Hello) -> QString {
|
||||
let hello = unsafe { &mut *ptr };
|
||||
QString::from(hello.get_hello())
|
||||
pub unsafe extern fn hello_get(ptr: *const Hello) -> QString {
|
||||
QString::from((&*ptr).get_hello())
|
||||
}
|
||||
|
||||
|
||||
|
@ -85,7 +84,7 @@ pub trait RItemModelTrait<T> {
|
|||
fn row_count(&mut self, parent: QModelIndex) -> c_int;
|
||||
fn index(&mut self, row: c_int, column: c_int, parent: QModelIndex) -> QModelIndex;
|
||||
fn parent(&self, index: QModelIndex) -> QModelIndex;
|
||||
fn data<'a>(&'a mut self, index: QModelIndex, role: c_int) -> Variant<'a>;
|
||||
fn data(&mut self, index: QModelIndex, role: c_int) -> Variant;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -99,38 +98,32 @@ pub extern fn ritemmodel_new(qobject: *const RItemModelQObject, new_data_ready:
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_free(ptr: *mut RItemModel) {
|
||||
let ritemmodel = unsafe { Box::from_raw(ptr) };
|
||||
ritemmodel.emit().clear();
|
||||
pub unsafe extern fn ritemmodel_free(ptr: *mut RItemModel) {
|
||||
Box::from_raw(ptr).emit().clear();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_column_count(ptr: *mut RItemModel, parent: QModelIndex) -> i32 {
|
||||
let ritemmodel = unsafe { &mut *ptr };
|
||||
ritemmodel.column_count(parent)
|
||||
pub unsafe extern fn ritemmodel_column_count(ptr: *mut RItemModel, parent: QModelIndex) -> i32 {
|
||||
(&mut *ptr).column_count(parent)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_row_count(ptr: *mut RItemModel, parent: QModelIndex) -> i32 {
|
||||
let ritemmodel = unsafe { &mut *ptr };
|
||||
ritemmodel.row_count(parent)
|
||||
pub unsafe extern fn ritemmodel_row_count(ptr: *mut RItemModel, parent: QModelIndex) -> i32 {
|
||||
(&mut*ptr).row_count(parent)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_index(ptr: *mut RItemModel, row: i32, column: i32, parent: QModelIndex) -> QModelIndex {
|
||||
let ritemmodel = unsafe { &mut *ptr };
|
||||
ritemmodel.index(row, column, parent)
|
||||
pub unsafe extern fn ritemmodel_index(ptr: *mut RItemModel, row: i32, column: i32, parent: QModelIndex) -> QModelIndex {
|
||||
(&mut *ptr).index(row, column, parent)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_parent(ptr: *const RItemModel, index: QModelIndex) -> QModelIndex {
|
||||
let ritemmodel = unsafe { &*ptr };
|
||||
ritemmodel.parent(index)
|
||||
pub unsafe extern fn ritemmodel_parent(ptr: *const RItemModel, index: QModelIndex) -> QModelIndex {
|
||||
(&*ptr).parent(index)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn ritemmodel_data(ptr: *mut RItemModel, index: QModelIndex, role: c_int, d: *mut c_void, set: fn (*mut c_void, &QVariant)) {
|
||||
let ritemmodel = unsafe { &mut *ptr };
|
||||
let data = ritemmodel.data(index, role);
|
||||
pub unsafe extern fn ritemmodel_data(ptr: *mut RItemModel, index: QModelIndex, role: c_int, d: *mut c_void, set: fn (*mut c_void, &QVariant)) {
|
||||
let data = (&mut *ptr).data(index, role);
|
||||
set(d, &QVariant::from(&data));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
use libc::{c_int};
|
||||
use types::*;
|
||||
use testinterface::*;
|
||||
|
||||
pub struct Test {
|
||||
emit: TestEmitter,
|
||||
username: String,
|
||||
age: c_int,
|
||||
active: bool,
|
||||
misc: Variant
|
||||
}
|
||||
|
||||
impl TestTrait for Test {
|
||||
fn create(emit: TestEmitter) -> Test {
|
||||
Test {
|
||||
emit: emit,
|
||||
username: String::new(),
|
||||
age: 0,
|
||||
active: true,
|
||||
misc: Variant::None
|
||||
}
|
||||
}
|
||||
fn emit(&self) -> &TestEmitter {
|
||||
&self.emit
|
||||
}
|
||||
fn get_username(&self) -> String { self.username.clone() }
|
||||
fn set_username(&mut self, value: String) {
|
||||
self.username = value;
|
||||
self.emit.username_changed();
|
||||
}
|
||||
fn get_age(&self) -> c_int {
|
||||
self.age
|
||||
}
|
||||
fn get_active(&self) -> bool {
|
||||
self.active
|
||||
}
|
||||
fn set_active(&mut self, value: bool) {
|
||||
self.active = value;
|
||||
self.emit.active_changed();
|
||||
}
|
||||
fn get_misc(&self) -> Variant { Variant::None }
|
||||
fn set_misc(&mut self, value: Variant) {
|
||||
self.misc = value;
|
||||
self.emit.misc_changed();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
use libc::{c_int, c_uint, uint8_t};
|
||||
use std::slice;
|
||||
use libc::{c_int, c_uint, uint8_t, uint16_t};
|
||||
use std::ptr::null;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -8,6 +9,21 @@ pub struct QString {
|
|||
len: c_int
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct QStringIn {
|
||||
data: *const uint16_t,
|
||||
len: c_int
|
||||
}
|
||||
|
||||
impl QStringIn {
|
||||
pub fn convert(&self) -> String {
|
||||
let data = unsafe {
|
||||
slice::from_raw_parts(self.data, self.len as usize)
|
||||
};
|
||||
String::from_utf16_lossy(data)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a String> for QString {
|
||||
fn from(string: &'a String) -> QString {
|
||||
QString {
|
||||
|
@ -17,31 +33,25 @@ impl<'a> From<&'a String> for QString {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum Variant<'a> {
|
||||
pub enum Variant {
|
||||
None,
|
||||
Bool(bool),
|
||||
String(String),
|
||||
Str(&'a str)
|
||||
ByteArray(Vec<u8>)
|
||||
}
|
||||
|
||||
impl<'a> From<bool> for Variant<'a> {
|
||||
fn from(value: bool) -> Variant<'a> {
|
||||
impl From<bool> for Variant {
|
||||
fn from(value: bool) -> Variant {
|
||||
Variant::Bool(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<String> for Variant<'a> {
|
||||
fn from(value: String) -> Variant<'a> {
|
||||
impl From<String> for Variant {
|
||||
fn from(value: String) -> Variant {
|
||||
Variant::String(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Variant<'a> {
|
||||
fn from(value: &'a str) -> Variant {
|
||||
Variant::Str(value)
|
||||
}
|
||||
}
|
||||
|
||||
/* values from qvariant.h and qmetatype.h */
|
||||
#[repr(u32)]
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -64,33 +74,37 @@ impl<'a> QVariant<'a> {
|
|||
pub fn type_(&self) -> u32 {
|
||||
self.type_ as u32
|
||||
}
|
||||
pub fn convert(&self) -> Variant {
|
||||
// TODO
|
||||
Variant::None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a Variant<'a>> for QVariant<'a> {
|
||||
fn from(variant: &'a Variant<'a>) -> QVariant {
|
||||
match variant {
|
||||
&Variant::None => QVariant {
|
||||
impl<'a> From<&'a Variant> for QVariant<'a> {
|
||||
fn from(variant: &'a Variant) -> QVariant {
|
||||
match *variant {
|
||||
Variant::None => QVariant {
|
||||
data: null(),
|
||||
len: 0,
|
||||
type_: VariantType::Invalid as c_uint,
|
||||
phantom: PhantomData
|
||||
},
|
||||
&Variant::Bool(v) => QVariant {
|
||||
Variant::Bool(v) => QVariant {
|
||||
data: null(),
|
||||
len: v as c_int,
|
||||
type_: VariantType::Bool as c_uint,
|
||||
phantom: PhantomData
|
||||
},
|
||||
&Variant::String(ref v) => QVariant {
|
||||
Variant::String(ref v) => QVariant {
|
||||
data: v.as_ptr(),
|
||||
len: v.len() as c_int,
|
||||
type_: VariantType::String as c_uint,
|
||||
phantom: PhantomData
|
||||
},
|
||||
&Variant::Str(ref v) => QVariant {
|
||||
Variant::ByteArray(ref v) => QVariant {
|
||||
data: v.as_ptr(),
|
||||
len: v.len() as c_int,
|
||||
type_: VariantType::String as c_uint,
|
||||
type_: VariantType::ByteArray as c_uint,
|
||||
phantom: PhantomData
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# Bindings between Qt and Rust
|
||||
|
||||
## Glossary
|
||||
|
||||
### Property type
|
||||
|
||||
The type that is written in the JSON file. This is the type that is type that
|
||||
is used in the C++ code.
|
||||
|
||||
### binding type
|
||||
|
||||
The type that is used to transer the data between the Rust and Qt.
|
||||
|
||||
### C++ binding type
|
||||
|
||||
The C++ version of the type that is transferred between Rust and Qt.
|
||||
|
||||
### Rust binding type
|
||||
|
||||
The Rust version of the type that is transferred between Rust and Qt.
|
||||
|
|
@ -355,11 +355,13 @@ extern "C" {
|
|||
}
|
||||
|
||||
QString rustType(const Property& p) {
|
||||
/*
|
||||
if (p.type == "QVariant") {
|
||||
return "Variant";
|
||||
}
|
||||
*/
|
||||
if (p.type.startsWith("Q")) {
|
||||
return "&" + p.type.mid(1);
|
||||
return p.type.mid(1);
|
||||
}
|
||||
if (p.type == "int") {
|
||||
return "c_int";
|
||||
|
@ -407,7 +409,7 @@ pub trait %1Trait {
|
|||
)").arg(o.name);
|
||||
for (const Property& p: o.properties) {
|
||||
const QString lc(p.name.toLower());
|
||||
const bool q = p.type.startsWith("Q");
|
||||
// const bool q = p.type.startsWith("Q");
|
||||
r << QString(" fn get_%1(&self) -> %2;\n").arg(lc, rustType(p));
|
||||
if (p.write) {
|
||||
r << QString(" fn set_%1(&mut self, value: %2);\n").arg(lc, rustType(p));
|
||||
|
@ -435,11 +437,47 @@ pub extern fn %2_new(qobject: *const %1QObject)").arg(o.name, lcname);
|
|||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn %2_free(ptr: *mut %1) {
|
||||
let d = unsafe { Box::from_raw(ptr) };
|
||||
d.emit().clear();
|
||||
pub unsafe extern fn %2_free(ptr: *mut %1) {
|
||||
Box::from_raw(ptr).emit().clear();
|
||||
}
|
||||
)").arg(o.name, lcname);
|
||||
for (const Property& p: o.properties) {
|
||||
const QString base = QString("%1_%2").arg(lcname, p.name.toLower());
|
||||
QString ret = ") -> " + rustType(p);
|
||||
if (p.type.startsWith("Q")) {
|
||||
r << QString(R"(
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn %2_get(ptr: *const %1, p: *mut c_void, set: fn (*mut c_void, %4)) {
|
||||
let data = (&*ptr).get_%3();
|
||||
set(p, %4::from(&data));
|
||||
}
|
||||
)").arg(o.name, base, p.name.toLower(), p.type);
|
||||
if (p.write) {
|
||||
const QString type = p.type == "QString" ? "QStringIn" : p.type;
|
||||
r << QString(R"(
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn %2_set(ptr: *mut %1, v: %4) {
|
||||
(&mut *ptr).set_%3(v.convert());
|
||||
}
|
||||
)").arg(o.name, base, p.name.toLower(), type);
|
||||
}
|
||||
} else {
|
||||
r << QString(R"(
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn %2_get(ptr: *const %1) -> %4 {
|
||||
(&*ptr).get_%3()
|
||||
}
|
||||
)").arg(o.name, base, p.name.toLower(), rustType(p));
|
||||
if (p.write) {
|
||||
r << QString(R"(
|
||||
#[no_mangle]
|
||||
pub unsafe extern fn %2_set(ptr: *mut %1, v: %4) {
|
||||
(&mut *ptr).set_%3(v);
|
||||
}
|
||||
)").arg(o.name, base, p.name.toLower(), rustType(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString rustFile(const QDir rustdir, const QString& module) {
|
||||
|
@ -458,8 +496,9 @@ void writeRustInterface(const Configuration& conf) {
|
|||
}
|
||||
QTextStream r(&file);
|
||||
r << QString(R"(
|
||||
use std::slice;
|
||||
use libc::{c_int, uint16_t, size_t, c_void};
|
||||
#![allow(unknown_lints)]
|
||||
#![allow(mutex_atomic, needless_pass_by_value)]
|
||||
use libc::{c_int, c_void};
|
||||
use types::*;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::ptr::null;
|
||||
|
|
Loading…
Reference in New Issue