C struct/union member cannot be a memory view

442 views
Skip to first unread message

GiorgosR

unread,
Nov 30, 2020, 10:28:18 AM11/30/20
to cython-users
Hi all,

I am trying to build a cython extension (which can be successfully built with Cython 0.24) with Cython 0.29. However, I am getting the following compiler error:

 "C struct/union member cannot be a memory view"

In my entension, I have defined C like struct as:

cdef struct Solution:
    double[:,::1] u
    double[:, ::1] u_n
    double dx
    Py_ssize_t x_size

where later on they are passed in class members via std::vectors to shape their views 

"cdef void initialise_solution_vector(self, vector[U] &vectorU, int length)"

The error is self-explanatory, however, I am trying to find what has it been changed between 0.24 and 0.29. I guess that definition was wrong and it should not be compiled via Cython 0.24.

How can I define the struct above in Cython > 0.24? The shape is not known at compile time. Should I use a class instead and shape the views upon object instantiation? Could somebody give me a optimum way so as to do not change a lot in my code.

Many thanks and best regards,
Giorgos

da-woods

unread,
Dec 1, 2020, 3:02:53 PM12/1/20
to cython...@googlegroups.com
It shouldn't have compiled on earlier versions - memoryviews need Cython to do reference counting and isn't able to track them when they're bundled into a struct. You'd probably have had a memory leak in your earlier version.

Two options are
1. Replace the struct with a cdef class (although you probably can't put it in a c++ vector).
2. Replace the memoryviews with a pointer and length (for the 1D one) or a pointer with 2 lengths (for the 2D one).
--

---
You received this message because you are subscribed to the Google Groups "cython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cython-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cython-users/865c420c-1f5f-4e2a-b51f-0c8bea96efe6n%40googlegroups.com.


Giorgos Ragkousis

unread,
Dec 3, 2020, 5:05:58 AM12/3/20
to cython...@googlegroups.com
Hi there, 

Many thanks for your reply.

I am thinking of implementing the second option. However, I am not sure what is the best way to copy/cast the C arrays to memoryviews (so as to do not change the method signatures that accept memoryviews).

If I have a C array, "double* arr" with length equal to "d", is the method below the most efficient for copying all array to contents into a memoryview?

cdef double[::1] _view = <double[:d]>arr

Many thanks in advance

You received this message because you are subscribed to a topic in the Google Groups "cython-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/cython-users/3QLjQbRQHY4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to cython-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cython-users/705f6a6d-e728-c8fd-0e06-64ac6a25834c%40d-woods.co.uk.


--
Georgios Ragkousis



da-woods

unread,
Dec 5, 2020, 8:17:04 AM12/5/20
to cython...@googlegroups.com
Yes - that's the way to get a memoryview from a pointer.

Note that it's a *view* of the array not a copy of the array - changing the memoryview will edit your original memory.

GiorgosR

unread,
Dec 7, 2020, 11:41:05 AM12/7/20
to cython-users
Hi,

Ok, many thanks for this. It works fine for the case of 1D c arrays (e.g. cdef double* c_array). However, when trying to cast 2D arrays (cdef double** c_arr) as:

cdef double[:, ::1] view = <double[:_rows, :_cls:1]>(c_arr)

, I am getting compiler error:

"Pointer base type does not match cython.array base type"

what am I missing here?

da-woods

unread,
Dec 7, 2020, 3:44:42 PM12/7/20
to cython...@googlegroups.com
That 2D arrays are stored internally as a 1D array plus size/strides. They are not stored as a pointer-to-pointer.

Cython memoryviews do support indirect arrays in principle but you need some wrapper code (e.g. https://github.com/realead/indirect_buffer) - I'd really recommend using a 1D array as your storage instead.
Reply all
Reply to author
Forward
0 new messages