Uh oh!
There was an error while loading. Please reload this page.
Support syntax for passing struct in CPython - #1814
Conversation
czgdp1807
commented
May 16, 2023
I am not sure if it fixes #1799 entirely. Could you please add tests from that issue to actually see if they work with your change? |
ubaidsk
commented
May 16, 2023
@czgdp1807 do you mean to add the example in #1799 (comment) as an integration_test? |
czgdp1807
commented
May 16, 2023
Yes. |
ubaidsk
commented
May 16, 2023
@czgdp1807 added it. Thank you for the guidance. |
| foos[0] = Foo(5, 21) | ||
| def main0() -> None: | ||
| foos: Foo[1] = empty(1, dtype=Foo) |
There was a problem hiding this comment.
I would just support the Array[] syntax for arrays of structs, like this:
| foos: Foo[1] =empty(1, dtype=Foo) | |
| foos: Array[Foo, 1] =empty(1, dtype=Foo) |
Then it should be possible to implement this cleanly in lpython.py as well as LPython.
certik
left a comment
There was a problem hiding this comment.
I think as a quick fix it is fine. I think it might break if Foo already defines __class_getitem__ or if it supports the [] like syntax. Right now LPython doesn't support it, so it's fine. But in the long run I think we will have to support the Array[Foo] syntax.
dylon
commented
May 16, 2023
This does not work in CPython, right now, because |
ubaidsk
commented
May 16, 2023
Please, could you share an example which fails? |
dylon
commented
May 16, 2023
Sure, this reminds me of a bug I need to report that I worked around: #1817 With the workaround above, the following fails with the message above: fromlpythonimportCPtr, c_p_pointer, p_c_pointer, dataclass, empty_c_void_p, pointer, Pointerfromnumpyimportempty@dataclassclassFoo:
passdefbar(foos_ptr: CPtr) ->None:
foos: Pointer[Foo[:]] =c_p_pointer(foos_ptr, Foo[:])
defmain() ->None:
foos: Foo[1] =empty(1, dtype=Foo)
foos_ptr: CPtr=empty_c_void_p()
p_c_pointer(pointer(foos), foos_ptr)
bar(foos_ptr)
main() |
certik
commented
May 16, 2023
It's weird that it works at our CI. I wonder if it is Python version dependent. Or our CI is broken? |
dylon
commented
May 16, 2023
This almost works, but leads to another bug (again, branching off my workaround from above): #1818 defdataclass(arg):
def__class_getitem__(idxs):
returnArray(arg, idxs)
arg.__class_getitem__=__class_getitem__returnpy_dataclass(arg) |
certik
commented
May 17, 2023
I created a dedicated issue for all the bugs reported in the last few comments above: #1819, so that we don't forget about this. We'll investigate and fix it. |
The code posted in #1814 (comment) will not work with CPython because for dataclasses because numpy just creates an array of Python objects. See below, fromlpythonimportdataclass, i32fromnumpyimportempty@dataclassclassFoo:
x: i32y: i32@dataclassclassFoe:
x: i32y: i32z: i32defmain() ->None:
foos=empty(2, dtype=Foo)
print(foos.dtype)
foos[0] =Foo(1, 2)
foos[1] =Foe(3, 4, 5)
print(foos[0], foos[1])
main()(lp) 15:11:37:~/lpython_project/lpython % python /Users/czgdp1807/lpython_project/debug.py
object
Foo(x=1, y=2) Foe(x=3, y=4, z=5)So we won't be able to use fromlpythonimportCPtr, c_p_pointer, p_c_pointer, dataclass, empty_c_void_p, pointer, Pointerfromnumpyimportempty@dataclassclassFoo:
passdefbar(foos_ptr: CPtr) ->None:
foos: Pointer[Foo[:]] =c_p_pointer(foos_ptr, Foo[:])
defmain() ->None:
foos: Foo[1] =empty(1, dtype=Foo)
foos_ptr: CPtr=empty_c_void_p()
p_c_pointer(pointer(foos, Foo), foos_ptr)
bar(foos_ptr)
main()with the following diff, diff --git a/src/runtime/lpython/lpython.py b/src/runtime/lpython/lpython.py
index c6c53cf31..a82a190f8 100644
--- a/src/runtime/lpython/lpython.py+++ b/src/runtime/lpython/lpython.py@@ -448,6 +448,8 @@ def pointer(x, type_=None):
type_ = type(x)
from numpy import ndarray
if isinstance(x, ndarray):
+ if py_is_dataclass(type_):+ return x
return x.ctypes.data_as(ctypes.POINTER(convert_numpy_dtype_to_ctype(x.dtype)))
else:
if type_ == i8: |
czgdp1807
commented
May 17, 2023
Also see #1822. Luck by chance I also ended up with #1814 (comment). |
Related - #1799.