Boost logo

Boost :

From: David Abrahams (abrahams_at_[hidden])
Date: 2000-11-02 23:16:47


----- Original Message -----
From: "Anton Gluck" <gluc_at_[hidden]>

> 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.

-Dave


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk