-
Notifications
You must be signed in to change notification settings - Fork 678
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sharing pyclasses between multiple Rust packages #1444
Comments
After getting great help from you in #1535 I've hit this issue. The additional feature I want to add would still make use of multiple objects defined in the parent package. But alas, as you say, Python thinks they aren't the same object and fails to convert the object into an object it actually already is. 😅 |
Yeah; unfortunately unlike #1535 this one's hard and I haven't thought more than the words above as to how it might work. I'm also not planning to design a solution any time soon as there's a number of big pieces of work in the pyO3 core which I think are higher priority. If this is something you need sooner rather than later, I suggest having a go at this yourself based on my sketch above and asking questions liberally on this issue for anything which you need help understanding. It should be possible to cobble something together for this without needing to change the current pyO3 crate itself. No guarantees it won't be painful though! |
Thanks, it is helpful all the same. I just might take you up on that offer to cobble something together. Albeit, I've started paternity leave so won't have anything up for some time most likely. We'll see how things go. Thanks again. 👍 |
No rush & congratulations! |
While dabbling with this earlier today, I hit #1193; thinking entering pyclasses into a capsule could be a good avenue for sharing structs/functions between crates. Is it not an absurd approach for when that issue is solved? |
Possibly - why were you thinking of using capsules rather than using Python APIs to import the Python objects directly? Or were you thinking of putting function pointers to supporting Rust functions in the capsules? I believe numpy might do something like that. |
I was indeed taking inspiration from pyo3 numpy and this description about using capsules seemed to reinforce my plan.
Is there any benefit/loss from doing it this way vs capsules? Naively, it seemed like there would be some overhead going through Python to get an object/pyclass vs the capsule workflow. |
Yeah, especially if you're just exporting Rust functions which you don't want to wrap in Python at all, then capsules are very much a suitable tool. |
Hi everyone, We have a similar issue, we have a crate So far we are able to build My take from the previous posts is that this is still not possible, I'm correct? Nevermind, I solved this by introducing an indirection between crate |
Another update, I still find some issues when the data comes back from Python to Rust, in detail the
While the types are defined in crate |
Unfortunately that I think the solution is stll the one in my OP - don't statically link the shared dependency into the final extension-modules and instead import symbols from it as a dynamic library. This way there should only be on static type object ever created (in the dynamic library) which is then loaded everywhere. But as in the OP, this is hard, and neither Cargo nor PyO3 really think about this case yet. |
That was exactly what I was thinking, make crate |
ah, I think I hit this issue in datafusion-contrib/datafusion-python#45 (comment) as well |
The upshot of this discussion seems to be that if one has a situation where one defines some Rust structs in module A, which are also exported to Python, and wants to write more Rust code that takes as arguments those structs from Python, then one had better put that Rust code into module A, and not into a module B. Would that be accurate? I'm not complaining -- just want to verify what the state of play is. I'm new to all this, so .... still learning. |
For now, building everything as one big module A is much much easier than having split modules A and B, yes. |
Hi, just pinging this, I started using PyO3 recently with my Rust project, and so far it's fine, but I'm worried I'll run into this issue when I implement the whole library structure I'm going for. Basically I have a |
I've also run into this issue. For reference, here's a minimal repor demo. |
I've seen several questions about re-using
#[pyclass]
types between multiple Rust packages, for example on gitter, stack overflow and most recently in #1418.This issue is indended to be a place for the discussion to centralize regarding understanding the difficulties in this and to brainstorm solutions / API designs which we can add to PyO3.
Below is my write-up of the issue. Note that I haven't tried to any of this myself; this is just where I think the difficulties are. I could be totally wrong - please use this thread to share evidence, ask questions, and test ideas.
Let's call package
A
the "original" package, which defines a#[pyclass] MyClass
. PackageB
is a child crate which makes use ofuse a::MyClass
in Rust code, to re-use the pyclass.The key issue is that
#[pyclass]
stores the pyclass type object instatic
storage. This means that (if Rust's usualrlib
linkage is used) packagesA
andB
will have their own copies of theMyClass
type object, and Python will think that they're actually different types coming from the two packages.I think the core of the solution to this is to make
B
link against the packageA
C shared library - the same.so
file which Python usess to load packageA
. ThenB
should be able to re-use the pyclass fromA
.This comes with a few steps:
A
will need to export additional symbols whichB
can use. This probably includes at a minimum theMyClass
static type object, and probably functions for convertingPyAny
<->MyClass
.B
will need to useA
as a "C" dependency which it links to using anextern "C"
block, where it imports symbols fromA
.B
will be able touse a::MyClass;
at all - it may need to have a duplicate definition which uses the exported symbols internally.Looking at that, it might mean that we'd eventually have
pyclass_export!
andpyclass_import!
macros in PyO3 to help with this.The above is all a poorly-worded brain dump of what might be a solution. I'm really not sure - anyone who is trying to do this, please comment, ask questions, provide error logs, and we can figure this out together.
The text was updated successfully, but these errors were encountered: