Mapping between runtime types and C/compile-time types
- Status: Idea
This is just Dag Sverre's draft for now; I'll start a discussion on the mailing list when it is a better time for it.
This is a feature which helps bridge the gap between C types and Python types in instances where the entire state of the object can be accurately represented by a variable of a native C type. The primary use case is with the ctypes module as well as the datatypes declared in numpy.
cdef classes (or, cdef classes in pxd-files which overlay the names of Python counterpart classes?) can implement two new operator overloads, __tocvar__ and __fromcvar__.
1 cdef class c_uint: 2 cdef final inline unsigned int __tocvar__(object x): 3 return <unsigned int>(c_uint(x).value) 4 cdef final inline object __fromcvar__(unsigned int x): 5 return c_uint(x)
The functions should only be used if the entire state of the object can be accurately represented by a variable of a native C type. (This includes C++ classes used in "stack mode", i.e. not allocated on the heap).
These functions are considered static methods, and do not take the "self" parameter. Also they must be declared cdef (and, if implemented in a pxd file, final).
__tocvar__ should have a native C type (or a typedef of such) as the return type, and take an object as first parameter.
__fromcvar__ is symmetric to this, it takes the same native C type as the first parameter and must have object as return type.
- Both or none of the functions must be provided.
The most important point is that when these functions are provided, cdef c_uint x no longer has the traditional meaning (declare the x variable as a reference/pointer to a c_uint object). Instead, the variable x is declared to be of the return type of __tocvar__. Effectively a type alias is created so that in type context, c_uint means unsigned int.
In addition the functions are called when doing conversion between the variable and Python objects. Such conversion is fully automatic and considered to be lossless.
Operator overloading is not considered. I.e. it is expected that normal C operations on the variable will provide the right results.
Finally, the run-time type is of course the class itself.
Examples build on the pxd file declared above.
1 cdef c_uint x = 8 2 c_func(x + 4)
This only uses c_uint as a convenient typedef, and is completely equivalent to
1 cdef unsigned int x = 8 2 c_func(x + 4)
Note that the + operator is going to be handled C-side.
1 o = 8 2 cdef c_uint x = o 3 print x 4 print c_uint
This is equivalent to the following:
1 o = 8 2 cdef unsigned int x = <unsigned int>(c_uint(o).value) 3 print c_uint(x) 4 print c_uint
Line 4 demonstrates how c_uint refers to the Python c_uint class object.