Tenho duas caixas Rust lib1
e lib2
, para as quais uso pyo3
para gerar ligações. Importo a caixa lib1
em lib2
.
Em um crape separado lib1-py
, crio uma classe python MyClass
e, em lib2
, tento usar MyClass
como parâmetro para uma função Python, usando:
fn foo(param: PyRef<MyClass>)
Eu uso separadamente maturin
para construir ambos lib1-py
no lib2
mesmo ambiente.
Quando tento executar o código python:
import lib1
import lib2
param = lib1.MyClass()
lib2.foo(param)
Eu obtenho o erro TypeError: argument 'param': 'MyClass' object cannot be converted to ‘MyClass’
.
Suponho que o sistema de caixas do Rust tenta ser seguro, tratando tipos de caixas diferentes como entidades separadas, mesmo que sejam idênticas. Como eu poderia resolver esse problema?
Em geral, isso é impossível. O Rust nem sequer garante
MyClass
que haverá os mesmos layouts de memória em ambas as compilações.É possível projetar a lib1-py para permitir isso. Por exemplo, se a totalidade de
MyClass
is#[repr(C)]
(ou seja, ele e todos os seus campos são, recursivamente), você pode pegar aBound<PyAny>
e convertê-lo paraBound<MyClass>
withinto_ptr()
andfrom_owned_ptr()
. Embora esse seja um método perigoso; se algo algum dia se tornar not ,#[repr(C)]
seu código ficará inseguro.Um método provavelmente melhor (e o que, por exemplo, Polars faz) é ter um método para serializar
MyClass
em algum formato, acessível em Python, e um método correspondente para desserializar (que não precisa ser acessível em Python). Então, você pegaBound<PyAny>
e chama esse método e desserializa o resultado.