Skip to content

Add a store of Rust classes to PyContext - #857

Closed
coolreader18 wants to merge 2 commits into
masterfrom
coolreader18/ctx-rust-classes
Closed

coolreader18 wants to merge 2 commits into
masterfrom
coolreader18/ctx-rust-classes

Conversation

@coolreader18

Copy link
Copy Markdown
Member

I extracted this from #848, and I plan to add an extends capability to #[pyclass], but that also depends on this feature and I didn't want to put all of that in #848. Also, I feel like this is a good compromise for how to store classes like json.JSONDecodeError - builtin types are still stored as struct fields, but you also have the capability to map an arbitrary Rust type to a class. It's certainly more performant than looking it up as a string key of a module dict!

Comment thread vm/src/pyobject.rs
}

pub fn _get_class(&self, typeid: &TypeId) -> Option<PyClassRef> {
self.rust_classes.borrow_mut().get(typeid).cloned()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to use borrow_mut here, we are not mutating the mapping.

@windelbouwman

Copy link
Copy Markdown
Contributor

@coolreader18 thank's for your work on this. Getting a member from the module itself is not solved well at this point. I have mixed feelings about this change. On the one hand, it solves the issue of getting a rust type from the VM in a better way, rather then getting it via a get module hack. On the other hand, we still require the module if we want to retrieve a variable or function.

One other remark, with this route we store all rust classes of all modules on the pycontext, this potentially exposes all classes to all modules. I don't think this is the way to go.

I think is better to provide a mechanism such that each function in a module has access to its containing module. Maybe by extending the magic argument types with a OwnModule type like this:

#[pymethod(name="foo")
fn foo(vm: VirtualMachine, module: OwnModule, x: PyIntRef) {
  // use module here
  module.get_attr('')
}

Or maybe we can use a closure to fix this? Something like this:

fn make_module() {

SocketClass = py_class!();

#[pymethod(name="foo")
fn foo(vm: VirtualMachine, x: PyIntRef) -> SocketClass {
   SocketClass
}

}

In other words, I am not convinced this is the way to go.

@coolreader18

Copy link
Copy Markdown
Member Author

What do you think about struct modules then? i.e. a module would be defined as a struct with specifically defined fields as well as a string-keyed dict, stored somewhere as just a dyn Any, and you would call maybe ctx.get_module::<OsModule>() to get it. That way, you could only access it if you can get a reference to a type that it corresponds to (which, btw, is how this rust_classes implementation works), so if you make that module struct private, it's completely encapsulated.

@windelbouwman

Copy link
Copy Markdown
Contributor

Yeah, I think that is already better. It sort of duplicates the sys.modules dictionary, but in a more fail safe way. Still I feel we could do something with scopes at the module sourcecode file level.

@coolreader18

Copy link
Copy Markdown
Member Author

What you were describing with a fn declaration inside of the make_module function wouldn't work, because inline function declarations aren't closures; they can't capture any of the variables around them like ||{} closures can, and defining every function in a module as a closure would be sort of painful.

@windelbouwman

Copy link
Copy Markdown
Contributor

Okay, in that case I prefer to keep the current system with the strings. This also works, although it is a bit weird. Lets wait for the opinions of other reviewers.

@coolreader18

Copy link
Copy Markdown
Member Author

I'm currently working on a struct modules implementation, which would eliminate the need for this. Should we close this for now?

@windelbouwman

Copy link
Copy Markdown
Contributor

Maybe leave this open to allow the others to have a look at this idea. What is the idea with the struct modules?

@coolreader18

Copy link
Copy Markdown
Member Author

A RefCell<HashMap<TypeId, dyn Any>> stored on PyContext, and store_module<T>(&self, module: T) and get_module<T>(&self) -> T methods. I think T would be required to be Clone so we could get it out of the HashMap .

@coolreader18

Copy link
Copy Markdown
Member Author

Or maybe get_module could accept a closure so someone could only clone what they need from the stored module.

@coolreader18
coolreader18 deleted the coolreader18/ctx-rust-classes branch October 26, 2021 14:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants