[C++-sig] C++ const -> Python immutable?
Philip Austin
paustin at eos.ubc.ca
Wed Sep 25 22:41:26 CEST 2002
Ralf W. Grosse-Kunstleve writes:
>
> Now it seems to me that both by_reference and by_const_reference
> work, but that the "const" is lost. Is this correct? Ralf
This is one step further than I've managed to get, and I'm wondering
whether someone could point out the errors in the following program,
or suggest another approach. The goal is to have a simple wrapper
(numhandle) that holds an object containing a PyArrayObject*. Given
any python sequence, numpy can produce a deep copy with:
a) PyArray_CopyFromObject(o,PyArray_NOTYPE,0,0)))
and either an incremented reference or a deep
copy with:
b) PyArray_ContiguousFromObject(o,PyArray_NOTYPE,0,0)))
Below I try to invoke a) with the function:
numhandle pass_by_value(numhandle theArray)
and b) with
numhandle pass_by_reference(numhandle& theArray)
(I also try to return a reference, but instantiating
numhandle_to_python_reference() causes the compiler
to complain as noted on the line tagged Error: below).
The code compiles, but the results aren't what
I expect viz:
In python:
import Numeric as N
import num_test_ext as nt
thearray=N.arange(3,typecode=N.Float32)
print "python calls pass by value"
print nt.pass_by_value(thearray)
produces:
python calls pass by value
inside reference constructor
inside pass_by_value[ 999. 1. 2.]
i.e. the reference constructor is called, even though
the signature is:
numhandle pass_by_value(numhandle theArray)
Next I try calling:
numhandle pass_by_reference(numhandle& theArray)
in python:
print "python calls pass by reference"
print nt.pass_by_reference(thearray)
which yields:
python calls pass by reference
Traceback (most recent call last):
File "<stdin>", line 12, in ?
TypeError: bad argument type for built-in operation
Many thanks, Phil Austin
numhandle.cpp:__________________________________
#include <boost/python/def.hpp>
#include <boost/python/module_init.hpp>
#include <boost/python/object_core.hpp>
#include <iostream>
#include <Numeric/arrayobject.h>
using namespace boost::python;
struct numhandle {
object pyholder;
};
struct register_numhandle_from_python_by_value
{
register_numhandle_from_python_by_value()
{
converter::registry::insert(&convertible,
&construct, type_id<numhandle>());
}
static void* convertible(PyObject* o)
{
std::cout << "inside value convertible check" << std::endl;
if (!PySequence_Check(o)){
return NULL;
}
return o;
}
static void construct (PyObject* o,
converter::rvalue_from_python_stage1_data* data)
{
std::cout << "inside value constructor" << std::endl;
void* storage = ((converter::rvalue_from_python_storage<numhandle>*)
data)->storage.bytes;
object newo(detail::new_reference(
PyArray_CopyFromObject(o,PyArray_NOTYPE,0,0)));
new (storage) numhandle();
data->convertible = storage;
numhandle& result = *((numhandle*) storage);
result.pyholder=newo;
}
};
struct register_numhandle_from_python_by_reference
{
register_numhandle_from_python_by_reference()
{
converter::registry::insert(&convertible,
&construct, type_id<numhandle&>());
}
static void* convertible(PyObject* o)
{
if (!PySequence_Check(o)){
return NULL;
}
return o;
}
static void construct (PyObject* o,
converter::rvalue_from_python_stage1_data* data)
{
std::cout << "inside reference constructor" << std::endl;
void* storage = ((converter::rvalue_from_python_storage<numhandle>*)
data)->storage.bytes;
object newo(detail::new_reference(
PyArray_ContiguousFromObject(o,PyArray_NOTYPE,0,0)));
new (storage) numhandle();
data->convertible = storage;
numhandle& result = *((numhandle*) storage);
result.pyholder=newo;
}
};
struct numhandle_to_python_value :
to_python_converter<numhandle, numhandle_to_python_value>
{
static PyObject*
convert(numhandle x)
{
return incref(x.pyholder.ptr());
}
};
struct numhandle_to_python_reference :
to_python_converter<numhandle&, numhandle_to_python_reference>
{
static PyObject*
convert(numhandle& x)
{
return incref(x.pyholder.ptr());
}
};
numhandle pass_by_reference(numhandle& theArray){
float* thedata= (float*) ((PyArrayObject*) theArray.pyholder.ptr())->data;
thedata[0]=888.;
std::cout << "inside pass_by_reference";
return theArray;
}
numhandle pass_by_value(numhandle theArray){
float* thedata= (float*) ((PyArrayObject*) theArray.pyholder.ptr())->data;
std::cout << "inside pass_by_value";
thedata[0]=999.;
return theArray;
}
numhandle& return_a_reference(numhandle& theArray){
float* thedata= (float*) ((PyArrayObject*) theArray.pyholder.ptr())->data;
std::cout << "return a reference";
thedata[0]=777.;
return theArray;
}
BOOST_PYTHON_MODULE_INIT(num_test_ext)
{
using namespace boost::python;
import_array();
register_numhandle_from_python_by_value();
register_numhandle_from_python_by_reference();
numhandle_to_python_value();
//Error: the following won't compile, error
// message says "forming
// pointer to reference type `numhandle& const"
//numhandle_to_python_reference();
def("pass_by_reference", pass_by_reference);
def("pass_by_value", pass_by_value);
}
More information about the Cplusplus-sig
mailing list