<div dir="ltr"><div>I have started discussing with Nathaniel the implementation of the ufunc ABI break that he proposed in a draft NEP a few months ago:</div><div><br></div><div><a href="http://thread.gmane.org/gmane.comp.python.numeric.general/61270">http://thread.gmane.org/gmane.comp.python.numeric.general/61270</a><br></div><div><br></div>His original proposal was to make the public portion of <font face="monospace, monospace">PyUFuncObject</font> be:<div><br></div><div><div><div><font face="monospace, monospace">    typedef struct {</font></div><div><font face="monospace, monospace">        PyObject_HEAD</font></div><div><font face="monospace, monospace">        int nin, nout, nargs;</font></div><div><font face="monospace, monospace">    } PyUFuncObject;</font></div></div><div><br></div><div>Of course the idea is that internally we would use a much larger struct that we could change at will, as long as its first few entries matched those of <font face="monospace, monospace">PyUFuncObject</font>. My problem with this, and I may very well be missing something, is that in <font face="monospace, monospace">PyUFunc_Type</font> we need to set the <font face="monospace, monospace">tp_basicsize</font> to the size of the extended struct, so we would end up having to expose its contents. This is somewhat similar to what now happens with <font face="monospace, monospace">PyArrayObject</font>: anyone can <font face="monospace, monospace">#include "ndarraytypes.h"</font>, cast <font face="monospace, monospace">PyArrayObject*</font> to <font face="monospace, monospace">PyArrayObjectFields*</font>, and access the guts of the struct without using the supplied API inline functions. Not the end of the world, but if you want to make something private, you might as well make it truly private.</div><div><br></div><div>I think it would be to have something similar to what <font face="monospace, monospace">NpyIter</font> does::</div><div><br></div><div><div><font face="monospace, monospace">    typedef struct {</font></div><div><font face="monospace, monospace">        PyObject_HEAD</font></div><div><font face="monospace, monospace">        NpyUFunc *ufunc;</font></div><div><font face="monospace, monospace">    } PyUFuncObject;</font></div></div><div><br></div><div>where <span style="font-family:monospace,monospace">NpyUFunc</span> would, at this level, be an opaque type of which nothing would be known. We could have some of the <font face="monospace, monospace">NpyUFunc</font> attributes cached on the <font face="monospace, monospace">PyUFuncObject</font> struct for easier access, as is done in <font face="monospace, monospace">NewNpyArrayIterObject</font>. This would also give us more liberty in making <font face="monospace, monospace">NpyUFunc</font> be whatever we want it to be, including a variable-sized memory chunk that we could use and access at will. <font face="monospace, monospace">NpyIter</font> is again a good example, where rather than storing pointers to strides and dimensions arrays, these are made part of the <font face="monospace, monospace">NpyIter</font> memory chunk, effectively being equivalent to having variable sized arrays as part of the struct. And I think we will probably no longer trigger the Cython warnings about size changes either.</div><div><br></div><div>Any thoughts on this approach? Is there anything fundamentally wrong with what I'm proposing here?</div><div><br></div><div>Also, this is probably going to end up being a rewrite of a pretty large and complex codebase. I am not sure that working on this on my own and eventually sending a humongous PR is the best approach. Any thoughts on how best to handle turning this into a collaborative, incremental effort? Anyone who would like to join in the fun?</div><div><br></div><div>Jaime</div><div><br></div>-- <br><div>(\__/)<br>( O.o)<br>( > <) Este es Conejo. Copia a Conejo en tu firma y ayúdale en sus planes de dominación mundial.</div>
</div></div>