[C++-sig] lvalue converter (and other) questions

Ralf W. Grosse-Kunstleve rwgk at yahoo.com
Sat Aug 31 06:47:20 CEST 2002


> > Can I have a class_<shared<E> > at the same time?
> 
> Sure (why not?), but I'm not sure any longer that it will help you.
> 
> > How could bpl.so decide what
> > pops up the the Python layer?
> 
> I don't understand the question.

Say I have a function

shared<double> return_shared();

In Python:

a = return_shared()
type(a) # what will I get here?

As said, I want to see flex.double, not shared.double.

> Ralf, this is clearly a non-trivial problem, and I clearly don't yet
> understand it at a deep level.

Here is an idea for an implementation that would work for me.
It is a generalized version of the rvalue converter:

  template <typename WrappedType>
  struct lvalue_conversion_policy
  {
    BOOST_STATIC_CONSTANT(bool, enable_lvalue_conversion = false);

    // This is meant to be called after the function that uses the
    // lvalue returned, but before we get back to the Python interpreter.
    static void post_call(
      PyObject* obj_ptr,
      converter::rvalue_from_python_stage1_data* data)
    {
      // do nothing by default; should optimize away
    }
  };

  // Now the full specialization for a particular type.
  // Since we have to do without partial specialization I could
  // use inheritance to make this easy to use with multiple types.
  template <>
  struct lvalue_conversion_policy<shared<double> >
  {
    // Tell the registry that this should participate in lvalue conversions.
    BOOST_STATIC_CONSTANT(bool, enable_lvalue_conversion = true);

    typedef shared<double> shared_type;
    typedef versa<double, flex_grid<> > flex_type;

    static void post_call(
      PyObject* obj_ptr,
      converter::rvalue_from_python_stage1_data* data)
    {
      object obj(borrowed(obj_ptr));
      flex_type& a = extract<flex_type&>(obj)();
      assert(a.accessor().nd() == 1);
      assert(a.accessor().is_0_based());
      assert(!a.accessor().is_padded());
      shared_type& b = *(reinterpret_cast<shared_type*>(data->convertible));
      a.resize(flex_grid<>(b.size());
    }
  };

  template <typename SharedType>
  struct shared_from_flex
  {
    typedef typename SharedType::value_type element_type;
    typedef versa<element_type, flex_grid<> > flex_type;

    shared_from_flex()
    {
      converter::registry::push_back(
        &convertible,
        &construct,
        type_id<SharedType>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
      using namespace boost::python;
      object obj(borrowed(obj_ptr));
      extract<flex_type&> flex_proxy(obj);
      if (!flex_proxy.check()) return 0;
      flex_type& a = flex_proxy();
      if (a.accessor().nd() != 1) return 0;
      if (!a.accessor().is_0_based()) return 0;
      if (a.accessor().is_padded()) return 0;
      return obj_ptr;
    }

    static void construct(
      PyObject* obj_ptr,
      converter::rvalue_from_python_stage1_data* data)
    {
      using namespace boost::python;
      object obj(borrowed(obj_ptr));
      flex_type& a = extract<flex_type&>(obj)();
      assert(a.accessor().nd() == 1);
      assert(a.accessor().is_0_based());
      assert(!a.accessor().is_padded());
      void* storage = (
        (converter::rvalue_from_python_storage<SharedType>*)
          data)->storage.bytes;
      new (storage) SharedType(a);
      data->convertible = storage;
    }
  };

Is there hope that this or something similar could be done?
Thanks,
        Ralf


__________________________________________________
Do You Yahoo!?
Yahoo! Finance - Get real-time stock quotes
http://finance.yahoo.com




More information about the Cplusplus-sig mailing list