Trying to implement an object backing a tree model, I found that QString contents of a requested field (Bookmarks::data() -> String) were passed in an invalid way across the C/C++ boundary. The issue was that interface::QString was converted wrong into qstring_t, with mismatched pointer dereferences. The object in question: "Bookmarks": { "type": "Tree", "itemProperties": { "type_": { "type": "quint32", "roles": [ ["toolTip"] ] }, "name": { "type": "QString", "roles": [ ["display"] ] }, "count": { "type": "quint32", "roles": [ [], ["display"] ] } } } The affected field was `name`, thus the invalid function to read it: #[no_mangle] pub unsafe extern "C" fn bookmarks_data_name( ptr: *const Bookmarks, item: usize, d: *mut c_void, set: fn(*mut c_void, QString), ) { let data = (&*ptr).name(item); set(d, (data).into()); } The fixed function: #[no_mangle] pub unsafe extern "C" fn bookmarks_data_name( ptr: *const Bookmarks, item: usize, d: *mut c_void, set: fn(*mut c_void, &QString), // added pointer ) { let data = (&*ptr).name(item); let qs = (data).into(); set(d, &qs); // should be safe; a copy is made on the other side } The code to generate this is around line 360 in src/rust.cpp. The other side is line 932 in src/cpp.cpp
Created attachment 111974 [details] Workaround This works around the issue, and fixes failing test cases. Untested with rustByValue.
I'm not sure if the patch is actually the right place to tackle this problem. I would try to fix the behaviour of "rustByValue", but the way it's used seems opposite to me and I dare not touch it: { let data = (&*ptr).%3(); set(p, %5data.into()); } )").arg(o.name, base, snakeCase(p.name), p.type.name, p.rustByValue ?"&" :""); In the above snippet, the generated code will use a *reference* &data.into() iff rustByValue is *true*. Is this reversed?
This issue is fixed as of 57d557378ee629496b4a6afc58022f0677cdff06. The struct qstring_t is not present anymore. QString data is now passed as two pieces of data: the pointer to the characters and the length.