Check for const reference parameters in all from_python functions in py.h, including implementations.
Better python and C++ exception handling/error reporting.
long long support
use Python generic numeric coercion in from_python() for C++ numeric types
Rename PyPtr to Reference.
Report Cygwin linker memory issues
__init__ stuff
         Make abstract classes non-instantiable (?)
         Call default __init__ functions automatically where applicable (?)
Support for Python LONG types in Objects.h
Throw TypeError after asserting when objects from objects.cpp detect a type mismatch.
Figure out how to package everything as a shared library.
Unicode string support
Add read-only wrapper for __dict__ attribute
Objects.h support for generic objects, Sequence objects, etc.
empty() member functions for objects.hpp

Testing
    Python 2.0
    object revival in __del__
    More thorough tests of objects.h/cpp classes
    Better reference-count checking

Optimizations
    Remove one level of indirection on type objects (no vtbl?).
    Specializations of Caller<> for commmon combinations of argument types (?)
    Replace uses of XXXable classes
    Don't allocate instance __dict__ unless used.
    
        
Documentation:

    differences between Python classes and ExtensionClasses
        additional capabilities of ExtensionClasses
        slice adjustment

        Why special attributes other than __doc__ and __name__ are immutable.

            An example of the problems with the built-in Python classes.

            >>> class A:
            ...     def __getattr__(self, name):
            ...             return 'A.__getattr__'
            ...
            >>> class B(A): pass
            ...
            >>> class C(B): pass
            ...
            >>> C().x
            'A.__getattr__'
            >>> B.__bases__ = ()
            >>> C().x
            'A.__getattr__'

    Smart pointers
            #ifndef PY_NO_INLINE_FRIENDS_IN_NAMESPACE
            namespace py {
            #endif

            template <class T>
            struct VtkConverters
            {
                typedef py::PyExtensionClassConverters<T> Converters;

                friend vtk_ptr<T>& from_python(PyObject* p, py::Type<vtk_ptr<T>&>)
                    { return Converters::ptr_from_python(p, py::Type<vtk_ptr<T> >()); }

                friend vtk_ptr<T>& from_python(PyObject* p, py::Type<vtk_ptr<T> >)
                    { return Converters::ptr_from_python(p, py::Type<vtk_ptr<T> >()); }

                friend const vtk_ptr<T>& from_python(PyObject* p, py::Type<const vtk_ptr<T>&>)
                    { return Converters::ptr_from_python(p, py::Type<vtk_ptr<T> >()); }

                friend PyObject* to_python(vtk_ptr<T> x)
                    { return Converters::ptr_to_python(x); }
            };

            #ifndef PY_NO_INLINE_FRIENDS_IN_NAMESPACE
            }
            #endif

            template <class T>
            struct VtkWrapper : py::ClassWrapper<T>, py::VtkConverters<T>
            {
                typedef py::ClassWrapper<T> Base;
                VtkWrapper(Module& module, const char* name)
                    : Base(module, name) {}
            };

    exception handling

    Advanced Topics:
        Advanced Type Conversion
            adding conversions for fundamental types
                generic conversions for template types (with partial spec).

            Interacting with built-in Python objects and types from C++

            dealing with non-const reference/pointer parameters

        extending multiple-argument support using gen_all.py

    
    Fancy wrapping tricks
        templates
            Yes. If you look at the examples in extclass_demo.cpp you'll see that I have
            exposed several template instantiations (e.g. std::pair<int,int>) in Python.
            Keep in mind, however, that you can only expose a template instantiation,
            not a template. In other words, MyTemplate<Foo> can be exposed. MyTemplate
            itself cannot.

            Well, that's not strictly true. Wow, this is more complicated to explain
            than I thought.
            You can't make an ExtensionClass<MyTemplate>, since after all MyTemplate is
            not a type. You can only expose a concrete type to Python.

            What you *can* do (if your compiler supports partial ordering of function
            templates - MSVC is broken and does not) is to write appropriate
            from_python() and to_python() functions for converting a whole class of
            template instantiations to/from Python. That won't let you create an
            instance of MyTemplate<SomePythonType> from Python, but it will let you
            pass/return arbitrary MyTemplate<SomeCplusplusType> instances to/from your
            wrapped C++ functions.

            template <class T>
            MyTemplate<T> from_python(PyObject* x, py::Type<MyTemplate<T> >)
            {
               // code to convert x into a MyTemplate<T>... that part is up to you
            }

            template <class T>
            PyObject* from_python(const MyTemplate<T>&)
            {
               // code to convert MyTemplate<T> into a PyObject*... that part is up to
            you
            }

            For example, you could use this to convert Python lists to/from
            std::vector<T> automatically.

        Pointer return values
           
           Case 1:

                > I am now also able to wrap the problematic TextRecordIterator for Python.
                > However, one of its function compiles with this warning:
                >
                > d:\py_cpp/caller.h(33) : warning C4800: 'const class Record *const '
                > : forcing value to bool 'true' or 'false' (performance warning)
                >         d:\py_cpp/functions.h(54) : see reference to function template
                > instantiation 'struct _object *__cdecl py::Caller::call(const class Record
                > *const (__thiscall TextRecordIterator::*)(void),struct _object *,struct
                > _object *)' being compiled
                >
                > If you look at the offending code, you'll see that we really do need to
                > get back that pointer:
                >
                > const Record* const TextRecordIterator::Next() {
                >     if (fStatus != RecordIterator::SUCCESS) {
                >         return 0;
                >     } else {
                >         return &fData;
                >     }
                > }
                >
                > The point of the TextRecordIterator is to hand over one reord after
                > another. A bool wouldn't do us much good here :-)
                >
                > Do you have any suggestions for fixing this?

                In general, py_cpp doesn't automatically convert pointer return values
                to_python because pointers have too many potential meanings. Is it an
                iterator? A pointer to a single element? An array? Is ownership being passed
                to Python or is the pointer really just a reference? If the latter, what
                happens when some C++ code deletes the referent. The only exception to this
                rule is const char*, since it has a generally accepted interpretation (could
                be trouble with some generic code, though!)

                If you have wrapped the Record class, you could add this to namespace py:

                PyObject* to_python(const Record* p) {
                   return to_python(*p);
                }

                Of course, this will cause the Record class to be copied. If you can't live
                with that (Record would have to be /really/ heavyweight to make this
                worthwhile), you can follow one of these dangerous approaches:

                1. Use the technique I described with dangerous_array in
                http://www.egroups.com/message/boost/6196. You do not have to expose Record
                explicitly in this case. Instead the class you expose will be more of a
                Record_proxy

                2. Wrap Record in the usual way, then add the following to namespace py:

                PyObject* to_python(const Record* p)
                {
                    return ExtensionClass<Record>::ptr_to_python(const_cast<Record*>(p));
                }

                This will cause the Record* to be treated as though it were an owning smart
                pointer, even though it's not. Be sure you don't use the reference for
                anything from Python once the pointer becomes invalid, though. Don't worry
                too much about the const-correctness issue: Const-correctness is completely
                lost to Python anyway!

                3. As above, but instead wrap const Record rather than plain Record. Then
                you can avoid the const_cast, but you obviously can't def() any non-const
                member functions of Record.
           
           Case 2:

                > I have yet another question.  This is more a general wrapper question.
                > Let me say that there is a function that returns a float* which most
                > probably is an array.  Similarly if I have a function that takes a
                > float* as an argument, what is the best way of wrapping this?

                I think you have correctly perceived that it doesn't make sense for me to
                automatically convert all pointers, since the ownership semantics are so
                blurry.

                >   1) If the array is small it makes sense to convert it to either a
                >   tuple or list.  What is the easiest way to do this??  I am looking
                >   for a way that makes one write the least code. :)

                How can you tell the length of the array from a single pointer?
                Once you've answered that question, you can expose a wrapper function which
                returns an instance of the py::Tuple or py::List class from objects.h. If
                you are using a List, for example, you could write something like this:

                py::List wrap_f()
                {
                  T* start = f();
                  py::List x;
                  for (T* p = start; p != start + length_constant; ++p)
                     x.push_back(py::to_python(*p));
                  return x;
                }

                >   2) If the array is large it may not make sense to use a list/tuple
                >   esp. if the values are used for computationally intense programs.

                In this case you can do one of several somewhat dangerous things. Why
                dangerous? Because python can not control the lifetime of the data, so the
                data in the array may be destroyed or become invalid before the last
                reference to it disappears. The basic approach is to make a small C++ class
                which contains the pointer, and expose that:

                // UNTESTED
                template <class T>
                struct dangerous_array
                {
                    dangerous_array(T* start, T* end)
                        : m_start(start), m_end(end) {}

                    // exposed as "__len__"
                    std::size_t length() {
                        return m_end - m_start;
                    }

                    // exposed as "__getitem__"
                    T get_item(std::size_t n) {
                        check_range(n);
                        return start[n];
                    }

                    // exposed as "__setitem__" if the array is mutable
                    void set_item(std::size_t n, const T& x) {
                        check_range(n);
                        start[n] = x;
                    }
                 private:
                    void check_range(std::size_t n) {
                        if (n >= m_end - m_start)  {
                            PyErr_SetString(PyExc_IndexError, "array index out of range");
                            throw py::ErrorAlreadySet;
                        }
                    }
                    T* m_start;
                    T* m_end;
                };

                A reasonably safe approach would be to make a wrapper function for each
                function that returns a T*, and expose that instead. If you're too lazy and
                you really like to live on the edge, though, you can write to_python(T*) in
                terms of to_python(const dangerous_array<T>&), and you'll automatically
                convert all T* return values to a wrapped dangerous_array.

                >   3) For an arbitrary class "class_A", say, can py_cpp handle
                >   references to class_A &instance, or class_A *instance?? i.e. will it
                >   wrap function calls to such objects?  This question is obviously
                >   related to the earlier questions.

                Yes, iff class_A has been exposed to python with a  ClassWrapper<class_A>.
                See http://people.ne.mediaone.net/abrahams/downloads/under-the-hood.html for
                a few details.

        raw C++ arrays
            You could expose a function like this one to get the desired effect:

            #include <py_cpp/objects.h>
            void set_len(UnitCell& x, py::Tuple tuple)
            {
                double len[3];
                for (std::size_t i =0; i < 3; ++i)
                    len[i] = py::from_python(tuple[i].get(), py::Type<double>());
                x.set_len(len);
            }

        Types that are already wrapped by other libraries

                It's not documented yet, but you should be able to use a raw PyObject* or a
                py::Ptr as one parameter to your C++ function. Then you can manipulate it as
                any other generic Python object.

                Alternatively, If the NTL gives you a C/C++ interface, you can also write
                your own converter function:

                    some_ntl_type& from_python(PyObject* p, py::Type<some_NTL_type&>)
                    {
                        // an Example implementation. Basically, you need
                        // to extract the NTL type from the PyObject*.
                        if (p->ob_type != NTL_long_type) {
                            PyErr_SetString(PyExc_TypeErr, "NTL long required");
                            throw py::ArgumentError();
                        }
                        return *static_cast<some_NTL_type*>(p);
                    }

                then the C++ functions you're wrapping can take a some_NTL_type& parameter
                directly.

        "Thin converting wrappers" for constructors

            hijack some of the functionality
            described in the section on Overridable Virtual Functions (even though you
            don't have any virtual functions). I suggest this workaround:

            struct UnitCellWrapper : UnitCell
            {
                UnitCellWrapper(PyObject* self, py::Tuple x, py::Tuple y)
                    : UnitCell(from_python(x[1], py::Type<double>()),
                                    from_python(x[2], py::Type<double>()),
                                    from_python(x[3], py::Type<double>()),
                                    from_python(y[1], py::Type<double>()),
                                    from_python(y[2], py::Type<double>()),
                                    from_python(y[3], py::Type<double>()))
                {}
            }

            py::ClassWrapper<UnitCell, UnitCellWrapper> unit_cell_class;
            unit_cell_class.def(py::Constructor<py::Tuple, py::Tuple>());
            ...

        returning references to wrapped objects

        the importance of declaration order of ClassWrappers/ExtensionInstances

        out parameters and non-const pointers

        Calling back into Python:
          // caveat: UNTESTED!
          #include <py_cpp/pyptr.h>
          #include <py_cpp/callback.h>
          #include <py_cpp/py.h>
          #include <Python.h>
          int main()
          {
             try {
                 py::Ptr module(PyImport_ImportModule("weapons"));
                 const int strength = 10;
                 const char* manufacturer = "Vordon Empire";
                 py::Ptr a_blaster(py::Callback<py::Ptr>::call_method(
                          module.get(), "Blaster", strength, manufacturer));
                 py::Callback<void>::call_method(a_blaster.get(), "Fire");
                 int old_strength = py::Callback<int>::call_method(a_blaster.get(), "get_strength");
                 py::Callback<void>::call_method(a_blaster.get(), "set_strength", 5);
             }
             catch(...)
             {
             }
          }

    Miscellaneous
        About the vc6 project and the debug build
        About doctest.py

Boost remarks:

    > > One of us is completely nuts ;->. How can I move the test
    > > (is_prefix(enablers[i].name + 2, name + 2)) outside the loop if it
    depends
    > > on the loop index, i?
    > >
    >   name += 2;
    >    for()
    > {
    >    if (is_prefix(enablers[i].name + 2, name))
    > }

    I see now. I guess I should stop pussyfooting and either go for optimization
    or clarity here, eh?

    ------

    > Re: Dict                                                                      
    >    Why abbreviate this? Code is read 5 or 6 times for every time its          
    > written. The few extra characters don't affect compile time or program        
    > speed. It's part of my personal goal of write what you mean, name them        
    what                                                                            
    > they are.                                                                     
                                                                                    
    I completely agree. Abbrevs rub me the wrong way, 2 ;-> 
 
    -------


                                                                                    
                                                                                    
Later:
       keyword and varargs?
       Put explicit Type<> arguments at the beginnings of overloads, to make them look more like template instance specifications.

Known bugs
      can't handle 'const void' return values
      Who returns 'const void'? I did it once, by mistake ;)
