[C++-sig] Re: long long unsigned issue...
David Abrahams
dave at boost-consulting.com
Thu May 29 15:09:50 CEST 2003
"Milind Patil" <milind_patil at hotmail.com> writes:
> Coming to issue with long_ conversion that I have had.
> I constructed a toy example to experiment with the long_
> conversion issue. Recapping, given the class
>
> class Y {
> public:
> Y() : y(0L) { }
> Y(int y) : y(y) { }
> Y(long long unsigned int y) : y(y) { }
> Y(int s, const Y & y) : y(y << s) { }
> Y(Y const& rhs) : y(rhs.y) { }
> virtual ~Y() { }
>
> operator int() const { return y; }
>
> void operator=(Y const& y) {
> this->y = y.y;
> }
>
> long long unsigned int y;
> };
My point is that this is a *very* big toy, with lots of constructors
which look like they could potentially contend for the same input
arguments. Can't you reduce the problem you're having a little bit
more?
> that I would like to wrap to python:
>
> BOOST_PYTHON_MODULE(hello)
> {
> class_< Y, Y_Wrapper >("Y", init< >())
> .def(init< const Y & >())
> .def(init< int, const Y & >())
> .def(init< int >())
> .def(init< long long unsigned int >())
> .def_readwrite("y", &Y::y)
> .def("__int__", &Y::operator int)
> ;
> impilcitly_convertible<int, Y>();
> }
>
> The implicitly_converitble above is to facilitate conversion
> to Y(int, &Y) for python x = hello.Y(2, 24) etc.
> I wanted to add conversion capability from and to python
> long_
Do you need *implicit* conversion capability? Remember that implicit
conversions are generally un-Pythonic.
> which was possible via a wrapper class (again, something
> that pyste originally generated):
>
> namespace {
> struct Y_Wrapper: Y {
> Y_Wrapper (PyObject* self_) : Y(), self(self_) {}
> Y_Wrapper (PyObject* self_, int y) : Y(y), self(self_) {}
> Y_Wrapper (PyObject* self_, long long unsigned int y) : Y(y), self(self_) {}
> Y_Wrapper (PyObject* self_, int s, const Y& y) : Y(s,y), self(self_) {}
> Y_Wrapper (PyObject* self_, const Y& y) : Y(y), self(self_) {}
> Y_Wrapper (PyObject* self_, boost::python::long_ y) : Y(0), self(self_) {printf("hello
> long_");}
>
> PyObject* self;
> };
> }
>
> and adding
>
> .def(init< long_ >())
>
> to module definition.
>
> So far so good. With your recent fixes it works perfectly for python
> construction of Y from long eg. x = hello.Y(4294967295) -- this is
> the type b constructor in the constructors I enumerated above. But
> if I want to construct signals of given width, then I would have x =
> signal(127,0, 4294967295), or x = hello.Y(127, 4294967295) for the
> toy example. This statement will cause a runtime exception fault
> saying that "OverflowError: long int too large to convert to int",
> probably because it is trying construct to Y(int s, const Y& y) and
> does not know how to make long_ to Y! My question here was :
>
> Now that we have a long_ to Y_Wrapper constructor
> and that class_ Y has Y_Wrapper as one of the bases
You got that backwards. Y is the base of Y_Wrapper.
> is it possible to use an implicity_convertible<long_, Y_Wrapper>();
> to be able to facilitate the conversion?
No, precisely because Y_Wrapper is not a base of Y.
The right solution to this problem is to provide for something Ralf
has been requesting for some time: the ability to inject new
constructors into a class, just the way we can inject methods that
aren't built from member functions. Something like:
Y Y_from_pylong(long_ y)
{
return Y(extract<unsigned long long>(y));
}
...
.def("__init__", constructor(Y_from_pylong))
> I am not comletely dead in water:
> I have added a .def(init<int, long_>) to module definition and a
> Y_Wrapper(PyObject* self_, int s, boost::python::long_ y)
> to Y_Wrapper to get around the inability to do a
> implicitly_convertible<long_ Y_Wrapper>() to effect the conversion.
> This works for me right now. I once again thank you for helping me
> with the issue I had.
>
> If you have read so far, I had some more observations as a user:
>
> Some of the use case scenarios for boost python are:
>
> a) Expose C++ classes as python classes alone. User will not derive
> from the exposed classes.
> b) Expose C++ classes as derivable classes in python.
a and b are equivalent as far as the library is concerned.
> c) Embedded scenarios with above two where it goes c++ to python to c++
> back etc.
Anything with, e.g., overridable virtual functions fits that picture.
It has nothing to do with embedding AFAICT... or am I missing
something?
> d) Expose C++ classes as derived or as convertible to python types (numeric,
> tuples, str etc.)
Case d can be combined with any of the other cases.
> My particular use case is a) and d). And there is adequate
> documentation/information to be able to be able to figure it out but it is
> difficult. Perhaps the document can handle c) and d) a little more?
I'm confused. Why do you want more info on c) if you don't use
Boost.Python that way?
> Anything I can help with?
Better support for your use cases has to come from two ends:
implementation and documentation. Part of the reason that d) isn't
better-documented is that its current implementation is too
complicated and low-level to expose to users. All of this can be
fixed by funding some library development.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
More information about the Cplusplus-sig
mailing list