py: Add support for native C classes to call Python methods of child instance #5660
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR is inspired by https://forum.micropython.org/viewtopic.php?f=3&t=7662 and the native module example at https://github.com/jamesbowman/py-bteve/tree/2407c82f852937bdf430cb12469e2b59ab588b3e/mpy, and also CircuitPython's fix adafruit#2550 (see adafruit@81c3bc4 and adafruit@f6a635b)
The aim is to allow Python classes to subclass native C classes (eg list) and for the C base class to then be able to call methods of the Python child instance. Eg:
except that we want to implement class
A
in native C code.Currently this is not possible to do because native classes get passed their native instance, even if the top-level object is a derived user instance (eg as
b
is above).One fix is to not extract out the native instance of derived user instances when invoking C methods, but instead pass the top-level instance to the C method. The problem with this is that all C methods must now be aware that they could be passed a user instance and must handle it accordingly.
The PR here does it a different way, by adding a new type flag that is set only on C classes that can handle a user instance coming in as the "self" argument to their C method. The advantage of this approach is that classes like tuple/list/dict that don't ever call methods of their inherited objects don't need to have this flag set and so don't need to change. Only C classes that want to support this feature can enable the flag (there will be overhead in code size and execution time for the C methods to test and extract the native instance).
This PR also exposes the new API function to dynamic native modules, and provides a new example of a dynamic native module that uses this feature (see original forum post linked above).
@tannewt FYI