0

I attempted to add #[pyclass] to a struct that includes Rc, but I encountered the following error.

error[E0277]: std::rc::Rc<MyStruct> cannot be sent between threads safely

Here's my source code:

struct MyStruct {
    name: String,
}

#[pyclass]
struct PyMyStruct {
    ptr: std::rc::Rc<MyStruct>,
}

How can I resolve this issue and successfully add #[pyclass] to a struct that uses Rc in PyO3?"

  • 2
    You probably should not do that because there is no guarantee that Python wouldn't send that value to other thread and use it from there. Rc is not Send and Sync for a reason. – Angelicos Phosphoros Jul 22 '23 at 14:22
  • 3
    It's actually possible to annotate the class as `#[pyclass(unsendable)]`, in which case `!Send` types are accepted, but they will be made to panic if accessed from an other thread than their creator, so using `Arc` is a *much* better idea. Or just doing nothing, Python classes are essentially already `Arc` pointers. – Masklinn Jul 22 '23 at 14:34
  • In fact, I am refactoring a single-threaded Python project's core, and I will ensure that this pointer will not be send to other threads. Using `#[pyclass(unsendable)]` should solve my problem. Thank you very much for all the help and support. – Jiamiao Hao Jul 23 '23 at 04:55

1 Answers1

2

From the PyO3 User Guide on Python classes:

Must be Send

Because Python objects are freely shared between threads by the Python interpreter, there is no guarantee which thread will eventually drop the object. Therefore all types annotated with #[pyclass] must implement Send (unless annotated with #[pyclass(unsendable)]).

Customizing the class

unsendable: Required if your struct is not Send. Rather than using unsendable, consider implementing your struct in a threadsafe way by e.g. substituting Rc with Arc. By using unsendable, your class will panic when accessed by another thread.

So if those limitations are acceptable, its straightforward:

#[pyclass(unsendable)]
struct PyMyStruct {
    ptr: Rc<MyStruct>,
}
kmdreko
  • 42,554
  • 6
  • 57
  • 106