Convert test_functions

master
Jos van den Oever 2018-05-12 13:58:43 +02:00
parent af7b64b82d
commit 67e6e8a9bf
5 changed files with 168 additions and 119 deletions

View File

@ -676,6 +676,38 @@ void constructorArgs(QTextStream& cpp, const QString& prefix, const Object& o, c
}
}
void writeFunctionCDecl(QTextStream& cpp, const Function& f, const QString& lcname, const Object& o) {
const QString lc(snakeCase(f.name));
cpp << " ";
if (f.type.isComplex()) {
cpp << "void";
} else {
cpp << f.type.name;
}
const QString name = QString("%1_%2").arg(lcname, lc);
cpp << QString(" %1(%3%2::Private*").arg(name, o.name, f.mut ? "" : "const ");
// write all the input arguments, for QString and QByteArray, write
// pointers to their content and the length
for (auto a = f.args.begin(); a < f.args.end(); a++) {
if (a->type.name == "QString") {
cpp << ", const ushort*, int";
} else if (a->type.name == "QByteArray") {
cpp << ", const char*, int";
} else {
cpp << ", " << a->type.rustType;
}
}
// If the return type is QString or QByteArray, append a pointer to the
// variable that will be set to the argument list. Also add a setter
// function.
if (f.type.name == "QString") {
cpp << ", QString*, qstring_set";
} else if (f.type.name == "QByteArray") {
cpp << ", QByteArray*, qbytearray_set";
}
cpp << ");\n";
}
void writeObjectCDecl(QTextStream& cpp, const Object& o, const Configuration& conf) {
const QString lcname(snakeCase(o.name));
cpp << QString(" %1::Private* %2_new(").arg(o.name, lcname);
@ -712,20 +744,7 @@ void writeObjectCDecl(QTextStream& cpp, const Object& o, const Configuration& co
}
for (const Function& f: o.functions) {
const QString lc(snakeCase(f.name));
const QString name = QString("%1_%2").arg(lcname, lc);
cpp << QString(" %1 %2(%4%3::Private*")
.arg(f.type.cSetType, name, o.name, f.mut ? "" : "const ");
if (f.args.size() > 0) {
cpp << ", ";
for (auto a = f.args.begin(); a < f.args.end(); a++) {
cpp << QString("%2%3").arg(a->type.cSetType, a + 1 < f.args.end() ? ", " : "");
}
}
if (f.type.name == "QString") {
cpp << ", QString*, qstring_set";
}
cpp << ");" << endl;
writeFunctionCDecl(cpp, f, lcname, o);
}
}
@ -883,10 +902,11 @@ void writeCppObject(QTextStream& cpp, const Object& o, const Configuration& conf
cpp << QString(")%1\n{\n")
.arg(f.mut ? "" : " const");
QString argList;
if (f.args.size() > 0) {
argList.append(", ");
for (auto a = f.args.begin(); a < f.args.end(); a++) {
argList.append(QString("%2%3").arg(a->name, a + 1 < f.args.end() ? ", " : ""));
for (auto a = f.args.begin(); a < f.args.end(); a++) {
if (a->type.name == "QString") {
argList.append(QString(", %2%3.utf16(), %2%3.size()").arg(a->name, a + 1 < f.args.end() ? ", " : ""));
} else {
argList.append(QString(", %2%3").arg(a->name, a + 1 < f.args.end() ? ", " : ""));
}
}
if (f.type.name == "QString") {

View File

@ -146,6 +146,91 @@ void rConstructorArgs(QTextStream& r, const QString& name, const Object& o, cons
r << ");\n";
}
void writeFunction(QTextStream& r, const Function& f, const QString& lcname, const Object& o) {
const QString lc(snakeCase(f.name));
r << QString(R"(
#[no_mangle]
pub extern "C" fn %1_%2(ptr: *%3 %4)").arg(lcname, lc, f.mut ? "mut" : "const", o.name);
// write all the input arguments, for QString and QByteArray, write
// pointers to their content and the length which is int in Qt
for (auto a = f.args.begin(); a < f.args.end(); a++) {
r << ", ";
if (a->type.name == "QString") {
r << QString("%1_str: *const c_ushort, %1_len: c_int").arg(a->name);
} else {
r << a->name << ": " << a->type.rustType;
}
}
// If the return type is QString or QByteArray, append a pointer to the
// variable that will be set to the argument list. Also add a setter
// function.
if (f.type.name == "QString") {
r << ", d: *mut QString, set: fn(*mut QString, str: *const c_char, len: c_int)) {\n";
} else if (f.type.name == "QByteArray") {
r << ", d: *mut QByteArray, set: fn(*mut QString, str: *const c_char, len: c_int)) {\n";
} else {
r << ") -> " << f.type.rustType << " {\n";
}
for (auto a = f.args.begin(); a < f.args.end(); a++) {
if (a->type.name == "QString") {
r << " let mut " << a->name << " = String::new();\n";
r << QString(" set_string_from_utf16(&mut %1, %1_str, %1_len);\n").arg(a->name);
} else if (a->type.name == "QByteArray") {
}
}
if (f.mut) {
r << " let o = unsafe { &mut *ptr };\n";
} else {
r << " let o = unsafe { &*ptr };\n";
}
r << " let r = o." << lc << "(";
for (auto a = f.args.begin(); a < f.args.end(); a++) {
if (a != f.args.begin()) {
r << ", ";
}
r << a->name;
}
r << ");\n";
if (f.type.isComplex()) {
r << " let s: *const c_char = r.as_ptr() as (*const c_char);\n";
r << " set(d, s, r.len() as i32);\n";
} else if (f.type.rustType != "()") {
r << " r\n";
}
r << "}\n";
/*
const QString type = a->type.name == "QString" ? "*const c_ushort, len: c_int" : a->type.rustType;
const QString passAlong = a->type.name == "QString" ? QString("%1.convert()").arg(a->name) : a->name;
argList.append(QString("%1: %2%3").arg(a->name, type, a + 1 < f.args.end() ? ", " : ""));
noTypeArgs.append(QString("%1%3").arg(passAlong, a + 1 < f.args.end() ? ", " : ""));
}
QString argList;
QString noTypeArgs;
if (f.args.size() > 0) {
argList.append(", ");
}
if (f.type.name == "QString") {
r << QString(R"(
#[no_mangle]
pub extern "C" fn %1_%2(ptr: *%3 %4%6, d: *mut QString, set: fn(*mut QString, str: *const c_char, len: c_int)) {
let o = unsafe { &%5*ptr };
let data = o.%2(%7);
let s: *const c_char = data.as_ptr() as (*const c_char);
set(d, s, data.len() as c_int);
}
)").arg(lcname, lc, f.mut ? "mut" : "const", o.name, f.mut ? "mut " : "", argList, noTypeArgs);
} else {
r << QString(R"(
#[no_mangle]
pub unsafe extern "C" fn %1_%2(ptr: *%3 %4%7) -> %5 {
(&%6*ptr).%2(%8)
}
)").arg(lcname, lc, f.mut ? "mut" : "const", o.name, f.type.rustType, f.mut ? "mut " : "", argList, noTypeArgs);
}
*/
}
void writeRustInterfaceObject(QTextStream& r, const Object& o, const Configuration& conf) {
const QString lcname(snakeCase(o.name));
r << QString(R"(
@ -455,35 +540,7 @@ pub unsafe extern "C" fn %2_set(ptr: *mut %1, v: %4) {
}
}
for (const Function& f: o.functions) {
const QString lc(snakeCase(f.name));
QString argList;
QString noTypeArgs;
if (f.args.size() > 0) {
argList.append(", ");
for (auto a = f.args.begin(); a < f.args.end(); a++) {
const QString type = a->type.name == "QString" ? "QStringIn" : a->type.rustType;
const QString passAlong = a->type.name == "QString" ? QString("%1.convert()").arg(a->name) : a->name;
argList.append(QString("%1: %2%3").arg(a->name, type, a + 1 < f.args.end() ? ", " : ""));
noTypeArgs.append(QString("%1%3").arg(passAlong, a + 1 < f.args.end() ? ", " : ""));
}
}
if (f.type.isComplex()) {
r << QString(R"(
#[no_mangle]
pub unsafe extern "C" fn %1_%2(ptr: *%3 %4%7, d: *mut c_void, set: fn(*mut c_void, %5)) {
let data = (&%6*ptr).%2(%8);
set(d, (&data).into());
}
)").arg(lcname, lc, f.mut ? "mut" : "const", o.name, f.type.name, f.mut ? "mut " : "", argList, noTypeArgs);
} else {
r << QString(R"(
#[no_mangle]
pub unsafe extern "C" fn %1_%2(ptr: *%3 %4%7) -> %5 {
(&%6*ptr).%2(%8)
}
)").arg(lcname, lc, f.mut ? "mut" : "const", o.name, f.type.rustType, f.mut ? "mut " : "", argList, noTypeArgs);
}
writeFunction(r, f, lcname, o);
}
if (o.type == ObjectType::List) {
r << QString(R"(
@ -867,10 +924,6 @@ void writeRustImplementationObject(QTextStream& r, const Object& o) {
r << QString(" %1: %2,\n").arg(lc, rustTypeInit(p));
}
}
if (o.type != ObjectType::Object) {
r << QString(" list: vec![%1Item::default(); 10],\n")
.arg(o.name);
}
r << QString(R"( }
}
fn emit(&self) -> &%1Emitter {

View File

@ -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;
@ -10,42 +11,17 @@ use std::ptr::null;
use implementation::*;
#[repr(C)]
pub struct QString {
data: *const uint8_t,
len: c_int,
pub enum QString {}
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 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(),
}
}
}
pub struct PersonQObject {}
@ -98,32 +74,44 @@ pub unsafe extern "C" fn person_free(ptr: *mut Person) {
}
#[no_mangle]
pub unsafe extern "C" fn person_user_name_get(
pub extern "C" fn person_user_name_get(
ptr: *const Person,
p: *mut c_void,
set: fn(*mut c_void, QString),
set: fn(*mut c_void, *const c_char, c_int),
) {
let data = (&*ptr).user_name();
set(p, data.into());
let o = unsafe { &*ptr };
let v = o.user_name();
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 person_user_name_set(ptr: *mut Person, v: QStringIn) {
(&mut *ptr).set_user_name(v.convert());
pub extern "C" fn person_user_name_set(ptr: *mut Person, 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_user_name(s);
}
#[no_mangle]
pub unsafe extern "C" fn person_double_name(ptr: *mut Person) -> () {
(&mut *ptr).double_name()
pub extern "C" fn person_double_name(ptr: *mut Person) -> () {
let o = unsafe { &mut *ptr };
let r = o.double_name();
}
#[no_mangle]
pub unsafe extern "C" fn person_greet(ptr: *const Person, Name: QStringIn, d: *mut c_void, set: fn(*mut c_void, QString)) {
let data = (&*ptr).greet(Name.convert());
set(d, (&data).into());
pub extern "C" fn person_greet(ptr: *const Person, Name_str: *const c_ushort, Name_len: c_int, d: *mut QString, set: fn(*mut QString, str: *const c_char, len: c_int)) {
let mut Name = String::new();
set_string_from_utf16(&mut Name, Name_str, Name_len);
let o = unsafe { &*ptr };
let r = o.greet(Name);
let s: *const c_char = r.as_ptr() as (*const c_char);
set(d, s, r.len() as i32);
}
#[no_mangle]
pub unsafe extern "C" fn person_vowels_in_name(ptr: *const Person) -> u8 {
(&*ptr).vowels_in_name()
pub extern "C" fn person_vowels_in_name(ptr: *const Person) -> u8 {
let o = unsafe { &*ptr };
let r = o.vowels_in_name();
r
}

View File

@ -44,6 +44,7 @@ void TestRustObject::testSimpleFunction()
person.setUserName("Konqi");
// THEN
QCOMPARE(person.userName(), QString("Konqi"));
QCOMPARE((int)person.vowelsInName(), 2);
}

View File

@ -3,22 +3,9 @@
namespace {
struct qstring_t {
private:
const void* data;
int len;
public:
qstring_t(const QString& v):
data(static_cast<const void*>(v.utf16())),
len(v.size()) {
}
operator QString() const {
return QString::fromUtf8(static_cast<const char*>(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);
}
inline void personUserNameChanged(Person* o)
{
@ -29,9 +16,9 @@ extern "C" {
Person::Private* person_new(Person*, void (*)(Person*));
void person_free(Person::Private*);
void person_user_name_get(const Person::Private*, QString*, qstring_set);
void person_user_name_set(Person::Private*, qstring_t);
void person_user_name_set(Person::Private*, const ushort *str, int len);
void person_double_name(Person::Private*);
qstring_t person_greet(const Person::Private*, qstring_t, QString*, qstring_set);
void person_greet(const Person::Private*, const ushort*, int, QString*, qstring_set);
quint8 person_vowels_in_name(const Person::Private*);
};
@ -62,7 +49,7 @@ QString Person::userName() const
return v;
}
void Person::setUserName(const QString& v) {
person_user_name_set(m_d, v);
person_user_name_set(m_d, reinterpret_cast<const ushort*>(v.data()), v.size());
}
void Person::doubleName()
{
@ -71,7 +58,7 @@ void Person::doubleName()
QString Person::greet(const QString& Name) const
{
QString s;
person_greet(m_d, Name, &s, set_qstring);
person_greet(m_d, Name.utf16(), Name.size(), &s, set_qstring);
return s;
}
quint8 Person::vowelsInName() const