[C++-sig] Internal compiler error with VC 6.0 and 7.0

Paul F. Kunz Paul_Kunz at SLAC.Stanford.EDU
Tue Nov 26 02:26:42 CET 2002


I'm using boost.python v2.   My Python extenstion module exposes C++
member functions having as arguments both "const vector < string > & " and
"const vector < double > &".   Using the boost.python FAQ, I've copied
relavent parts of Ralf's code into my own project.   All works fine
under Linux with both gcc 2.95.3 and gcc 3.2.1.   

Under Windows things worked with VC++ 7.0, but got "C1001: internal
compiler error" for VC++ 6.0.  Ok, I don't really need to do a build
with 6.0.  But then I made some changes, just moving files from one
directory to another ("famous last words" ) and now I have the "C1001"
for both 6.0 and 7.0.

If I comment out the for loop at the end of
from_python_sequence::convertible() member function of Ralf's code,
both VC++ 6.0 and 7.0 compile the code and it runs.

Any suggestions on what to do next?

For reference here is my version of Ralf's code...

---
/* -*- mode:c++ -*-
 * 
 * Boost.Python conversion functions to and from STL
 *
 * $Id: pyconversions.h,v 1.5 2002/11/25 23:34:19 pfkeb Exp $
 *
 */

#ifndef PY_CONVERSIONS_H
#define PY_CONVERSIONS_H

// BOOST_PYTHON_BEGIN_CONVERSION_NAMESPACE // this is a gcc 2.95.2 bug workaround
#include <boost/python.hpp>
using namespace boost::python;

/** A wrapper of a conversion function to convert a STL vector to a
    Python tuple.  This class statisfies the requirements of the
    boost::python::to_python_converter conversion template argument.

    Copied from scitbx/include/scitbx/boost_python/container_conversions.h
    @sa boost_1_29_0/libs/python/doc/v2/faq.html

    @author Ralf W. Grosse-Kunstleve <rwgk at yahoo.com> of 
    <a href="http://www.lbl.gov/">Lawrence Berkeley National Laboratory</a>
*/
  template < typename ContainerType>
  struct to_tuple
  {
    /** Creates and returns a Python @c tuple from the elements copied
	from a STL container. The @c ContainerType must be a vector,
	but may contain any type of object supported by the
	boost::python::object constructor. */
    static PyObject* convert ( ContainerType const& a)
    {
      using boost::python::incref; // works around gcc 2.96 bug
      using boost::python::list; // dito 
      list result;
      for(std::size_t i=0;i<a.size();i++) {
        result.append(object(a[i]));
      }
      return incref(tuple(result).ptr());
    }
  };

/** Converts an STL vector of T objects to Python tuple. 

    Copied from scitbx/include/scitbx/boost_python/container_conversions.h
    @sa boost_1_29_0/libs/python/doc/v2/faq.html

    @author Ralf W. Grosse-Kunstleve <rwgk at yahoo.com> of
    <a href="http://www.lbl.gov/">Lawrence Berkeley National Laboratory</a>
*/
  template < typename T >
  struct std_vector_to_tuple 
  {
    std_vector_to_tuple ()
    {
      to_python_converter < std::vector < T >, 
	                    to_tuple < std::vector < T > >  > ();
    }
  };

/** Default operations on all containers for conversion from Python
    container to C++ one.

    Copied from scitbx/include/scitbx/boost_python/container_conversions.h
    @sa boost_1_29_0/libs/python/doc/v2/faq.html

    @author Ralf W. Grosse-Kunstleve <rwgk at yahoo.com> of
    <a href="http://www.lbl.gov/">Lawrence Berkeley National Laboratory</a>
*/
  struct default_policy
  {
    static bool check_convertibility_per_element() { return false; }

    template <typename ContainerType>
    static bool check_size(boost::type<ContainerType>, std::size_t sz)
    {
      return true;
    }

    template <typename ContainerType>
    static void assert_size(boost::type<ContainerType>, std::size_t sz) {}

    template <typename ContainerType>
    static void reserve(ContainerType& a, std::size_t sz) {}
  };

/** Operations on containers that have variable capacity for
    conversion from Python container to C++ one.

    Copied from scitbx/include/scitbx/boost_python/container_conversions.h
    @sa boost_1_29_0/libs/python/doc/v2/faq.html

    @author Ralf W. Grosse-Kunstleve <rwgk at yahoo.com> of
    <a href="http://www.lbl.gov/">Lawrence Berkeley National Laboratory</a>
*/
  struct variable_capacity_policy : default_policy
  {
    template <typename ContainerType>
    static void reserve(ContainerType& a, std::size_t sz)
    {
      a.reserve(sz);
    }

    template <typename ContainerType, typename ValueType>
    static void set_value(ContainerType& a, std::size_t i, ValueType const& v)
    {
      assert(a.size() == i);
      a.push_back(v);
    }
  };

/** Conversion of Python sequence to C++ container.

    Copied from scitbx/include/scitbx/boost_python/container_conversions.h
    @sa boost_1_29_0/libs/python/doc/v2/faq.html

    @author Ralf W. Grosse-Kunstleve <rwgk at yahoo.com> of
    <a href="http://www.lbl.gov/">Lawrence Berkeley National Laboratory</a>
*/
  template <typename ContainerType, typename ConversionPolicy>
  struct from_python_sequence
  {
    typedef typename ContainerType::value_type container_element_type;

    from_python_sequence()
    {
      boost::python::converter::registry::push_back(
        &convertible,
        &construct,
        boost::python::type_id<ContainerType>());
    }

    /** Appears to return @a obj_ptr if it is type of Python sequence
	that can be convertible to C++ container. */
    static void* convertible(PyObject* obj_ptr)
    {
      using namespace boost::python;
      using boost::python::allow_null; // works around gcc 2.96 bug
      {
        // Restriction to list, tuple, iter, xrange until
        // Boost.Python overload resolution is enhanced.
        if (!(   PyList_Check(obj_ptr)
              || PyTuple_Check(obj_ptr)
              || PyIter_Check(obj_ptr)
              || PyRange_Check(obj_ptr))) return 0;
      }
      handle<> obj_iter(allow_null(PyObject_GetIter(obj_ptr)));
      if (!obj_iter.get()) { // must be convertible to an iterator
        PyErr_Clear();
        return 0;
      }
      if (ConversionPolicy::check_convertibility_per_element()) {
        int obj_size = PyObject_Length(obj_ptr);
        if (obj_size < 0) { // must be a measurable sequence
          PyErr_Clear();
          return 0;
        }
        if (!ConversionPolicy::check_size(
          boost::type<ContainerType>(), obj_size)) return 0;
        bool is_range = PyRange_Check(obj_ptr);
        //std::size_t i=0;
		int i = 0;
#ifndef _MSC_VER // because it causes c1001: internal compiler error
        for(;;i++) {
          handle<> py_elem_hdl(allow_null(PyIter_Next(obj_iter.get())));
          if (PyErr_Occurred()) {
            PyErr_Clear();
            return 0;
          }
          if (!py_elem_hdl.get()) break; // end of iteration
          object py_elem_obj(py_elem_hdl);
          extract<container_element_type> elem_proxy(py_elem_obj);
          if (!elem_proxy.check()) return 0;
          if (is_range) break; // in a range all elements are of the same type
        }
        if (!is_range) assert(i == obj_size );
#endif
      }
      return obj_ptr;
    }

    /** Constructs a C++ container from a Python sequence. */
    static void construct(
      PyObject* obj_ptr,
      boost::python::converter::rvalue_from_python_stage1_data* data)
    {
      using namespace boost::python;
      using boost::python::allow_null; // works around gcc 2.96 bug
      using boost::python::converter::rvalue_from_python_storage; // dito
      using boost::python::throw_error_already_set; // dito
      handle<> obj_iter(PyObject_GetIter(obj_ptr));
      void* storage = (
        (rvalue_from_python_storage<ContainerType>*)
          data)->storage.bytes;
      new (storage) ContainerType();
      data->convertible = storage;
      ContainerType& result = *((ContainerType*)storage);
      std::size_t i=0;
      for(;;i++) {
        handle<> py_elem_hdl(allow_null(PyIter_Next(obj_iter.get())));
        if (PyErr_Occurred()) throw_error_already_set();
        if (!py_elem_hdl.get()) break; // end of iteration
        object py_elem_obj(py_elem_hdl);
        extract<container_element_type> elem_proxy(py_elem_obj);
        ConversionPolicy::set_value(result, i, elem_proxy());
      }
      ConversionPolicy::assert_size(boost::type<ContainerType>(), i);
    }

  };

#endif // PY_CONVERSIONS_H

---
and the code in my Python module.

---
    /** Converts an STL vector of double to Python tuple. */
    std_vector_to_tuple < double > ();

    /** Converts an STL vector of string objects to Python tuple. */
    std_vector_to_tuple < std::string > ();

    /** Converts Python sequence of strings to vector of string. */
    from_python_sequence < std::vector < std::string >,
                           variable_capacity_policy > ();

    /** Converts Python sequence of double to vector of double. */
    from_python_sequence < std::vector < double >,
                           variable_capacity_policy > ();





More information about the Cplusplus-sig mailing list