Как энкапсулировать объект?
Как в pyo3 rust завернуть несовместимый с python объект и вернуть его в пайтон? Мне надо вернуть client_channels не используя pyclass (просто представьте что я его использовал с внешнего моделя). sleep тут здесь для теста GIL.
use pyo3::{prelude::*, wrap_pyfunction};
use tokio;
struct ClientChannels {
vendor_id: u16,
product_id: u16,
}
#[pyfunction]
fn sleep(py: Python) -> PyResult<Bound<PyAny>> {
let client_channels = ClientChannels {
vendor_id: 1,
product_id: 2,
};
pyo3_async_runtimes::tokio::future_into_py(py, async move {
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
Ok(client_channels)
})
}
#[pymodule]
fn libhidproxy(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(sleep, m)?)?;
Ok(())
}
Всё оказалось проще, достаточно указатель в виде целого вернуть.
use pyo3::{prelude::*, wrap_pyfunction};
use std::boxed::Box;
#[pyfunction]
fn create_client_channels() -> usize {
let client_channels = ClientChannels {
vendor_id: 1,
product_id: 2,
};
let boxed = Box::new(client_channels);
Box::into_raw(boxed) as usize
}
#[pyfunction]
fn get_vendor_id(ptr: usize) -> PyResult<u16> {
let channels = unsafe { &*(ptr as *const ClientChannels) };
Ok(channels.vendor_id)
}
#[pyfunction]
fn get_product_id(ptr: usize) -> PyResult<u16> {
let channels = unsafe { &*(ptr as *const ClientChannels) };
Ok(channels.product_id)
}
#[pyfunction]
fn free_client_channels(ptr: usize) -> PyResult<()> {
unsafe {
drop(Box::from_raw(ptr as *mut ClientChannels));
}
Ok(())
}
#[pymodule]
fn libhidproxy(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(create_client_channels, m)?)?;
m.add_function(wrap_pyfunction!(get_vendor_id, m)?)?;
m.add_function(wrap_pyfunction!(get_product_id, m)?)?;
m.add_function(wrap_pyfunction!(free_client_channels, m)?)?;
Ok(())
}