diff --git a/src/cpp.cpp b/src/cpp.cpp index 3c6ba8e..fd8bd9b 100644 --- a/src/cpp.cpp +++ b/src/cpp.cpp @@ -683,6 +683,8 @@ void writeObjectCDecl(QTextStream& cpp, const Object& o, const Configuration& co QString t = p.type.cSetType; if (t == "qstring_t") { t = "const ushort *str, int len"; + } else if (t == "qbytearray_t") { + t = "const char* bytes, int len"; } cpp << QString(" void %2_set(%1::Private*, %3);") .arg(o.name, base, t) << endl; @@ -834,10 +836,18 @@ void writeCppObject(QTextStream& cpp, const Object& o, const Configuration& conf cpp << QString(" if (v.isNull()) {") << endl; cpp << QString(" %1_set_none(m_d);").arg(base) << endl; cpp << QString(" } else {") << endl; - cpp << QString(" %1_set(m_d, v);").arg(base) << endl; + if (p.type.name == "QString") { + cpp << QString(" %1_set(m_d, reinterpret_cast(v.data()), v.size());").arg(base) << endl; + } else if (p.type.name == "QByteArray") { + cpp << QString(" %1_set(m_d, v.data(), v.size());").arg(base) << endl; + } else { + cpp << QString(" %1_set(m_d, v);").arg(base) << endl; + } cpp << QString(" }") << endl; } else if (p.type.name == "QString") { cpp << QString(" %1_set(m_d, reinterpret_cast(v.data()), v.size());").arg(base) << endl; + } else if (p.type.name == "QByteArray") { + cpp << QString(" %1_set(m_d, v.data(), v.size());").arg(base) << endl; } else { qWarning() << p.type.cppSetType; cpp << QString(" %1_set(m_d, v);").arg(base) << endl; @@ -932,22 +942,10 @@ namespace { } if (conf.types().contains("QByteArray")) { cpp << R"( - struct qbytearray_t { - private: - const char* data; - int len; - public: - qbytearray_t(const QByteArray& v): - data(v.data()), - len(v.size()) { - } - operator QByteArray() const { - return QByteArray(data, len); - } - }; - typedef void (*qbytearray_set)(QByteArray*, qbytearray_t*); - void set_qbytearray(QByteArray* v, qbytearray_t* val) { - *v = *val; + typedef void (*qbytearray_set)(QByteArray* val, const char* bytes, int nbytes); + void set_qbytearray(QByteArray* v, const char* bytes, int nbytes) { + v->truncate(0); + v->append(bytes, nbytes); } )"; } diff --git a/src/rust.cpp b/src/rust.cpp index 0f511e3..a34c3d6 100644 --- a/src/rust.cpp +++ b/src/rust.cpp @@ -371,45 +371,72 @@ pub extern "C" fn %2_get( set(p, s, v.len() as c_int); } )").arg(o.name, base, snakeCase(p.name), p.type.name, p.rustByValue ?"&" :""); - if (p.write) { - const QString type = p.type.name == "QString" ? "*const c_ushort, len: c_int" : p.type.name; + if (p.write && p.type.name == "QString") { r << QString(R"( #[no_mangle] -pub extern "C" fn %2_set(ptr: *mut %1, v: %4) { +pub extern "C" fn %2_set(ptr: *mut %1, v: *const c_ushort, len: c_int) { let o = unsafe { &mut *ptr }; let mut s = String::new(); set_string_from_utf16(&mut s, v, len); o.set_%3(s); } -)").arg(o.name, base, snakeCase(p.name), type); +)").arg(o.name, base, snakeCase(p.name)); + } else if (p.write) { + r << QString(R"( +#[no_mangle] +pub extern "C" fn %2_set(ptr: *mut %1, v: *const c_char, len: c_int) { + let o = unsafe { &mut *ptr }; + let v = unsafe { slice::from_raw_parts(v as *const u8, len as usize) }; + o.set_%3(v.into()); +} +)").arg(o.name, base, snakeCase(p.name)); } } else if (p.type.isComplex()) { r << QString(R"( #[no_mangle] -pub unsafe extern "C" fn %2_get( +pub extern "C" fn %2_get( ptr: *const %1, p: *mut c_void, - set: fn(*mut c_void, %4), + set: fn(*mut c_void, *const c_char, c_int), ) { - let data = (&*ptr).%3(); - if let Some(data) = data { - set(p, %5data.into()); + let o = unsafe { &*ptr }; + let v = o.%3(); + if let Some(v) = v { + let s: *const c_char = v.as_ptr() as (*const c_char); + set(p, s, v.len() as c_int); } } )").arg(o.name, base, snakeCase(p.name), p.type.name, p.rustByValue ?"&" :""); - if (p.write) { - const QString type = p.type.name == "QString" ? "QStringIn" : p.type.name; + if (p.write && p.type.name == "QString") { r << QString(R"( #[no_mangle] -pub unsafe extern "C" fn %2_set(ptr: *mut %1, v: %4) { - (&mut *ptr).set_%3(Some(v.convert())); +pub extern "C" fn %2_set(ptr: *mut %1, v: *const c_ushort, len: c_int) { + let o = unsafe { &mut *ptr }; + let mut s = String::new(); + set_string_from_utf16(&mut s, v, len); + o.set_%3(Some(s)); } #[no_mangle] -pub unsafe extern "C" fn %2_set_none(ptr: *mut %1) { - (&mut *ptr).set_%3(None); +pub extern "C" fn %2_set_none(ptr: *mut %1) { + let o = unsafe { &mut *ptr }; + o.set_%3(None); } -)").arg(o.name, base, snakeCase(p.name), type); +)").arg(o.name, base, snakeCase(p.name)); + } else if (p.write) { + r << QString(R"( +#[no_mangle] +pub extern "C" fn %2_set(ptr: *mut %1, v: *const c_char, len: c_int) { + let o = unsafe { &mut *ptr }; + let v = unsafe { slice::from_raw_parts(v as *const u8, len as usize) }; + o.set_%3(Some(v.into())); +} +#[no_mangle] +pub extern "C" fn %2_set_none(ptr: *mut %1) { + let o = unsafe { &mut *ptr }; + o.set_%3(None); +} +)").arg(o.name, base, snakeCase(p.name)); } } else { r << QString(R"( @@ -720,27 +747,7 @@ fn set_string_from_utf16(s: &mut String, str: *const c_ushort, len: c_int) { if (hasByteArray) { r << R"( -#[repr(C)] -pub struct QByteArray { - data: *const uint8_t, - len: c_int, -} - -impl QByteArray { - fn convert(&self) -> Vec { - let data = unsafe { slice::from_raw_parts(self.data, self.len as usize) }; - Vec::from(data) - } -} - -impl<'a> From<&'a [u8]> for QByteArray { - fn from(value: &'a [u8]) -> QByteArray { - QByteArray { - len: value.len() as c_int, - data: value.as_ptr(), - } - } -} +pub enum QByteArray {} )"; } if (hasListOrTree) { diff --git a/tests/rust_object_types/src/interface.rs b/tests/rust_object_types/src/interface.rs index 50b3f6a..abc7f5f 100644 --- a/tests/rust_object_types/src/interface.rs +++ b/tests/rust_object_types/src/interface.rs @@ -1,8 +1,9 @@ /* generated by rust_qt_binding_generator */ #![allow(unknown_lints)] #![allow(mutex_atomic, needless_pass_by_value)] -use libc::{c_int, c_void, uint8_t, uint16_t}; +use libc::{c_char, c_ushort, c_int, c_void, uint8_t, uint16_t}; use std::slice; +use std::char::decode_utf16; use std::sync::{Arc, Mutex}; use std::ptr::null; @@ -36,65 +37,20 @@ where } -#[repr(C)] -pub struct QString { - data: *const uint8_t, - len: c_int, -} +pub enum QString {} -#[repr(C)] -pub struct QStringIn { - data: *const uint16_t, - len: c_int, -} - -impl QStringIn { - 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 str> for QString { - fn from(string: &'a str) -> QString { - QString { - len: string.len() as c_int, - data: string.as_ptr(), - } - } -} - -impl<'a> From<&'a String> for QString { - fn from(string: &'a String) -> QString { - QString { - len: string.len() as c_int, - data: string.as_ptr(), - } - } +fn set_string_from_utf16(s: &mut String, str: *const c_ushort, len: c_int) { + let utf16 = unsafe { slice::from_raw_parts(str, len as usize) }; + let characters = decode_utf16(utf16.iter().cloned()) + .into_iter() + .map(|r| r.unwrap()); + s.clear(); + s.extend(characters); } -#[repr(C)] -pub struct QByteArray { - data: *const uint8_t, - len: c_int, -} -impl QByteArray { - fn convert(&self) -> Vec { - let data = unsafe { slice::from_raw_parts(self.data, self.len as usize) }; - Vec::from(data) - } -} - -impl<'a> From<&'a [u8]> for QByteArray { - fn from(value: &'a [u8]) -> QByteArray { - QByteArray { - len: value.len() as c_int, - data: value.as_ptr(), - } - } -} +pub enum QByteArray {} pub struct ObjectQObject {} @@ -231,18 +187,22 @@ pub unsafe extern "C" fn object_boolean_set(ptr: *mut Object, v: bool) { } #[no_mangle] -pub unsafe extern "C" fn object_bytearray_get( +pub extern "C" fn object_bytearray_get( ptr: *const Object, p: *mut c_void, - set: fn(*mut c_void, QByteArray), + set: fn(*mut c_void, *const c_char, c_int), ) { - let data = (&*ptr).bytearray(); - set(p, data.into()); + let o = unsafe { &*ptr }; + let v = o.bytearray(); + let s: *const c_char = v.as_ptr() as (*const c_char); + set(p, s, v.len() as c_int); } #[no_mangle] -pub unsafe extern "C" fn object_bytearray_set(ptr: *mut Object, v: QByteArray) { - (&mut *ptr).set_bytearray(v.convert()); +pub extern "C" fn object_bytearray_set(ptr: *mut Object, v: *const c_char, len: c_int) { + let o = unsafe { &mut *ptr }; + let v = unsafe { slice::from_raw_parts(v as *const u8, len as usize) }; + o.set_bytearray(v.into()); } #[no_mangle] @@ -256,60 +216,76 @@ pub unsafe extern "C" fn object_integer_set(ptr: *mut Object, v: i32) { } #[no_mangle] -pub unsafe extern "C" fn object_optional_bytearray_get( +pub extern "C" fn object_optional_bytearray_get( ptr: *const Object, p: *mut c_void, - set: fn(*mut c_void, QByteArray), + set: fn(*mut c_void, *const c_char, c_int), ) { - let data = (&*ptr).optional_bytearray(); - if let Some(data) = data { - set(p, data.into()); + let o = unsafe { &*ptr }; + let v = o.optional_bytearray(); + if let Some(v) = v { + let s: *const c_char = v.as_ptr() as (*const c_char); + set(p, s, v.len() as c_int); } } #[no_mangle] -pub unsafe extern "C" fn object_optional_bytearray_set(ptr: *mut Object, v: QByteArray) { - (&mut *ptr).set_optional_bytearray(Some(v.convert())); +pub extern "C" fn object_optional_bytearray_set(ptr: *mut Object, v: *const c_char, len: c_int) { + let o = unsafe { &mut *ptr }; + let v = unsafe { slice::from_raw_parts(v as *const u8, len as usize) }; + o.set_optional_bytearray(Some(v.into())); } #[no_mangle] -pub unsafe extern "C" fn object_optional_bytearray_set_none(ptr: *mut Object) { - (&mut *ptr).set_optional_bytearray(None); +pub extern "C" fn object_optional_bytearray_set_none(ptr: *mut Object) { + let o = unsafe { &mut *ptr }; + o.set_optional_bytearray(None); } #[no_mangle] -pub unsafe extern "C" fn object_optional_string_get( +pub extern "C" fn object_optional_string_get( ptr: *const Object, p: *mut c_void, - set: fn(*mut c_void, QString), + set: fn(*mut c_void, *const c_char, c_int), ) { - let data = (&*ptr).optional_string(); - if let Some(data) = data { - set(p, data.into()); + let o = unsafe { &*ptr }; + let v = o.optional_string(); + if let Some(v) = v { + let s: *const c_char = v.as_ptr() as (*const c_char); + set(p, s, v.len() as c_int); } } #[no_mangle] -pub unsafe extern "C" fn object_optional_string_set(ptr: *mut Object, v: QStringIn) { - (&mut *ptr).set_optional_string(Some(v.convert())); +pub extern "C" fn object_optional_string_set(ptr: *mut Object, v: *const c_ushort, len: c_int) { + let o = unsafe { &mut *ptr }; + let mut s = String::new(); + set_string_from_utf16(&mut s, v, len); + o.set_optional_string(Some(s)); } #[no_mangle] -pub unsafe extern "C" fn object_optional_string_set_none(ptr: *mut Object) { - (&mut *ptr).set_optional_string(None); +pub extern "C" fn object_optional_string_set_none(ptr: *mut Object) { + let o = unsafe { &mut *ptr }; + o.set_optional_string(None); } #[no_mangle] -pub unsafe extern "C" fn object_string_get( +pub extern "C" fn object_string_get( ptr: *const Object, p: *mut c_void, - set: fn(*mut c_void, QString), + set: fn(*mut c_void, *const c_char, c_int), ) { - let data = (&*ptr).string(); - set(p, data.into()); + let o = unsafe { &*ptr }; + let v = o.string(); + let s: *const c_char = v.as_ptr() as (*const c_char); + set(p, s, v.len() as c_int); } #[no_mangle] -pub unsafe extern "C" fn object_string_set(ptr: *mut Object, v: QStringIn) { - (&mut *ptr).set_string(v.convert()); +pub extern "C" fn object_string_set(ptr: *mut Object, v: *const c_ushort, len: c_int) { + let o = unsafe { &mut *ptr }; + let mut s = String::new(); + set_string_from_utf16(&mut s, v, len); + o.set_string(s); } #[no_mangle] diff --git a/tests/test_object_types_rust.cpp b/tests/test_object_types_rust.cpp index 1f7e27b..b095f23 100644 --- a/tests/test_object_types_rust.cpp +++ b/tests/test_object_types_rust.cpp @@ -3,40 +3,15 @@ namespace { - struct qstring_t { - private: - const void* data; - int len; - public: - qstring_t(const QString& v): - data(static_cast(v.utf16())), - len(v.size()) { - } - operator QString() const { - return QString::fromUtf8(static_cast(data), len); - } - }; - typedef void (*qstring_set)(QString*, qstring_t*); - void set_qstring(QString* v, qstring_t* val) { - *v = *val; + typedef void (*qstring_set)(QString* val, const char* utf8, int nbytes); + void set_qstring(QString* val, const char* utf8, int nbytes) { + *val = QString::fromUtf8(utf8, nbytes); } - struct qbytearray_t { - private: - const char* data; - int len; - public: - qbytearray_t(const QByteArray& v): - data(v.data()), - len(v.size()) { - } - operator QByteArray() const { - return QByteArray(data, len); - } - }; - typedef void (*qbytearray_set)(QByteArray*, qbytearray_t*); - void set_qbytearray(QByteArray* v, qbytearray_t* val) { - *v = *val; + typedef void (*qbytearray_set)(QByteArray* val, const char* bytes, int nbytes); + void set_qbytearray(QByteArray* v, const char* bytes, int nbytes) { + v->truncate(0); + v->append(bytes, nbytes); } inline void objectBooleanChanged(Object* o) { @@ -77,17 +52,17 @@ extern "C" { bool object_boolean_get(const Object::Private*); void object_boolean_set(Object::Private*, bool); void object_bytearray_get(const Object::Private*, QByteArray*, qbytearray_set); - void object_bytearray_set(Object::Private*, qbytearray_t); + void object_bytearray_set(Object::Private*, const char* bytes, int len); qint32 object_integer_get(const Object::Private*); void object_integer_set(Object::Private*, qint32); void object_optional_bytearray_get(const Object::Private*, QByteArray*, qbytearray_set); - void object_optional_bytearray_set(Object::Private*, qbytearray_t); + void object_optional_bytearray_set(Object::Private*, const char* bytes, int len); void object_optional_bytearray_set_none(Object::Private*); void object_optional_string_get(const Object::Private*, QString*, qstring_set); - void object_optional_string_set(Object::Private*, qstring_t); + void object_optional_string_set(Object::Private*, const ushort *str, int len); void object_optional_string_set_none(Object::Private*); void object_string_get(const Object::Private*, QString*, qstring_set); - void object_string_set(Object::Private*, qstring_t); + void object_string_set(Object::Private*, const ushort *str, int len); quint64 object_u64_get(const Object::Private*); void object_u64_set(Object::Private*, quint64); quint32 object_uinteger_get(const Object::Private*); @@ -135,7 +110,7 @@ QByteArray Object::bytearray() const return v; } void Object::setBytearray(const QByteArray& v) { - object_bytearray_set(m_d, v); + object_bytearray_set(m_d, v.data(), v.size()); } qint32 Object::integer() const { @@ -154,7 +129,7 @@ void Object::setOptionalBytearray(const QByteArray& v) { if (v.isNull()) { object_optional_bytearray_set_none(m_d); } else { - object_optional_bytearray_set(m_d, v); + object_optional_bytearray_set(m_d, v.data(), v.size()); } } QString Object::optionalString() const @@ -167,7 +142,7 @@ void Object::setOptionalString(const QString& v) { if (v.isNull()) { object_optional_string_set_none(m_d); } else { - object_optional_string_set(m_d, v); + object_optional_string_set(m_d, reinterpret_cast(v.data()), v.size()); } } QString Object::string() const @@ -177,7 +152,7 @@ QString Object::string() const return v; } void Object::setString(const QString& v) { - object_string_set(m_d, v); + object_string_set(m_d, reinterpret_cast(v.data()), v.size()); } quint64 Object::u64() const {