Skip to content
This repository has been archived by the owner on Feb 17, 2021. It is now read-only.

using rust and c++ in a Qt Creator project #44

Open
seshonaar opened this issue Apr 22, 2017 · 1 comment
Open

using rust and c++ in a Qt Creator project #44

seshonaar opened this issue Apr 22, 2017 · 1 comment

Comments

@seshonaar
Copy link

seshonaar commented Apr 22, 2017

Hi!

I'm currently trying to start from a standard Qt Creator project and delegate the "backend" to rust directly via ffi. But I still want to use c++ where the rust library doesn't have support yet (for example I need an QQuickImageProvider). I must say that I'm very close in achieving what I want, but I'm blocked by not having access to the native pointer of the QmlEngine. Do you think it would be possible to expose it to the external world, so it can be directly passed to c++?
Just as some code reference I have now: I'm creating the engine in rust, pass it back to c++ in order to do some extra stuff with it (ex: attaching the image provider) and then pass it back to rust and call exec()

pub struct DicomContext {
    engine: QmlEngine,
    controller: Box<QMainWindowController>
}

impl DicomContext {
    pub fn new() -> Self {
        let mut engine = QmlEngine::new();
        let main_controller = MainWindowController {};
        let q_controller = QMainWindowController::new(main_controller);
        engine.set_and_store_property("controller", q_controller.get_qobj());
        // Load main window QML
        engine.load_url("qrc:/main.qml");

        DicomContext { engine: engine, controller: q_controller }
    }
}

#[no_mangle]
pub extern "C" fn create_context() -> *mut DicomContext {
    // Create an instance of DicomContext. 
    let context = DicomContext::new(); 
 
    // Put named_data into a Box, which moves it onto the heap. 
    let boxed_data = Box::new(context); 
 
    // Convert our Box<DicomContext> into a *mut DicomContext. Rust is no longer 
    // managing the destruction of boxed_data; we must (at some point in the 
    // future) convert this pointer back into a Box<DicomContext> so it can be 
    // deallocated. 
    Box::into_raw(boxed_data)
}

#[no_mangle] 
pub extern fn get_engine(ptr: *mut DicomContext) -> *mut qml::types::WQmlApplicationEngine { 
    let core = unsafe { 
        assert!(!ptr.is_null()); 
        &mut *ptr 
    }; 
 
    core.engine.get_ptr() // I don't have this :|
}

#[no_mangle]
pub extern "C" fn run(ptr: *mut DicomContext)  {
    println!("running...");

    if ptr.is_null() { 
        return 
    }

    {
        let context = unsafe { 
            assert!(!ptr.is_null()); 
            &mut *ptr 
        }; 

        context.engine.exec();
        context.engine.quit();
    }

    // let rust handle freeing the memory
    unsafe { Box::from_raw(ptr); }
}
@seshonaar
Copy link
Author

and the c++ part
'''
#include
#include
#include
#include "dicomimageprovider.h"

struct DicomContext;

extern "C" {
void test_ffi();
DicomContext* create_context();
//QmlEngine* get_engine(DicomContext*);
void run(DicomContext*);
}

int main(int argc, char argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
DicomContext
context = create_context();
// here I need the engine back from rust...but I don't have it
//QQmlApplicationEngine* engine = get_engine(context);
//engine->addImageProvider(QLatin1String("dicom"), new DicomImageProvider);
run(context);
return 0;
}

'''

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant