Jim will have a lot more insight than I do into what constitutes a good response to his challenge. However, here are a few fairly superficial thoughts.
I found the way that identity of objects is managed to be fairly unidiomatic from a Python point of view. For example, adding a Doodad to a DoodadSet & then repeatedly calling as_list (or just list) on it returns a new Doodad object each time. Since they share the same underlying state that's not really a problem, but it doesn't feel like Python. (I'd imagine it could be a problem if I could set arbitrary attributes on the Doodad at Python level, but that's forbidden.) For example:
>>> a = object()
|
>>> l = []
|
>>> l.append(a)
|
>>> a is l.pop()
|
True
|
vs
>>> d = challenge.basics.Doodad("foo", 1)
|
>>> dds = challenge.containers.DoodadSet()
|
>>> dds.add(d)
|
>>> a is dds.as_list().pop()
|
False
|
On the subject of making things idiomatic, it would be nice to do better than:
>>> challenge.basics.Doodad(1, "foo")
|
TypeError: __init__() takes at least one string argument
|
Out of interest, why do we need to set macosx-version-min=10.7?
If the code were being merged to the stack, we'd be a bit pickier about coding standards (primarily, we don't like unexplained commented code). I don't think it's necessary to worry about that here though. I do wonder if a few more comments in the source would be helpful for future readers (especially since there may be several of them if this comparison goes out to a wider audience) but that's not strictly required given the existence of the tech note.
There are a few typos in the reST in the technote, which unfortunately have quite big impacts on the output – they cause a few code blocks not to be displayed properly and significant information is lost. Try the following:
--- a/index.rst
|
+++ b/index.rst
|
@@ -231,6 +231,7 @@ The C++ class ``Doodad`` also has a method called ``clone()`` that returns a ``u
|
which also requires ``std::move`` to be declared in the ``.pxd`` file.
|
|
.. code-block:: cython
|
+
|
cdef extern from "<utility>" namespace "std" nogil:
|
cdef shared_ptr[Doodad] move(unique_ptr[Doodad])
|
cdef shared_ptr[Doodad] move(shared_ptr[Doodad])
|
@@ -238,6 +239,7 @@ which also requires ``std::move`` to be declared in the ``.pxd`` file.
|
There are a few things annoying about this. One is that a separate specialization is to be declared for every type of move and the other is that Cython doesn't like it if two specializations have the same arguments but different return types. The following is thus not allowed.
|
|
.. code-block:: cython
|
+
|
cdef extern from "<utility>" namespace "std" nogil:
|
cdef unique_ptr[Doodad] move(unique_ptr[Doodad])
|
cdef shared_ptr[Doodad] move(unique_ptr[Doodad]) # error!
|
@@ -411,6 +413,7 @@ This is just to show how it can be done.
|
Of course ``begin()`` and ``end()`` have to be declared as well.
|
|
.. code-block:: cython
|
+
|
cdef extern from "containers.hpp" namespace "containers":
|
cdef cppclass DoodadSet:
|
vector[shared_ptr[Doodad]].const_iterator begin() const
|
@@ -438,10 +441,10 @@ These then use typemaps declared in ``basics_typemaps.i`` such as.
|
}
|
|
%typemap(in) std::shared_ptr<basics::Doodad> {
|
- if (!sptrFromDoodad($input, &$1)) {
|
- return nullptr;
|
+ if (!sptrFromDoodad($input, &$1)) {
|
+ return nullptr;
|
+ }
|
}
|
-}
|
|
The key to Cython / SWIG interoperability is of course in the functions ``newDoodadFromSptr`` (that should take a ``shared_ptr<Doodad>`` and return a Python object) and ``sptrFromDoodad`` (which does the opposite).
|
Finally, I realise that you just followed Jim's example by forking his repository to your personal account, but before we sign off on this issue I think we should make sure it's hosted in the lsst-dm organization on GitHub. I can create a repository there for you if you don't have permissions (which you probably don't) – assuming you don't object, give me a shout when you'd like me to do so.
A pull request for the code in the cython branch of my python-cpp-challenge fork has been sent to Jim.
A technote is available for review at https://github.com/lsst-dm/dmtn-013. Not sure how to assign it to anyone since it isn't a fork.