Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2002-11-07 07:48:19

Dan Nuffer <dnuffer_at_[hidden]> writes:

> Hi,
> I've started using Boost.Python to wrap some classes from OpenWBEM.
> So far I've got one class mostly done: OW_String. So far I have been
> very impressed, and think the library is great. But I've had a few
> problems. Here's some questions and comments:
> 2. Is is possible to wrap member functions which take a variable
> number of arguments (e.g. int format(const char* fmt, ...); ) ? I
> tried .def("format", &OW_String::format) but that doesn't work.

Not directly. Conversions from Python to C++ are "target-driven",
meaning that we need to know the type of the C++ argument in order to
make the conversion happen.

There are ways you can write a function which takes an arbitrary
number of Python objects in an argument tuple, and you can do the
dispatching yourself.

You could also consider supporting a fixed maximum number of arguments
by wrapping something like:

int format_dispatch(
    char const*fmt, object a0 = object(), object a1 =
    object()... object aN = object())
   // implementation details left up to you ;-)

> 3. OW_String has some methods like OW_String& concat(const
> OW_String& arg); which return *this;. I assume the correct return
> policy to use is return_internal_reference<>(). The documentation
> refers to the case where a reference is returned to an instance data
> member, but not the instance itself. Is return_internal_reference
> correct in this case?

Yeah, I guess so.

> 4. If the return policy is omitted from a member function which
> returns OW_String&, the error says: "specify_a_result_policy..." This
> should say return, not result, since the documentation doesn't mention
> result policies.

Picky, picky! OK, I'll fix that.

> 5. It would be nice if you gave an example in the tutorial about how
> to specify overloads, since casting the member function pointer is not
> something that is completely obvious (at least it took me a while to
> figure it out).


> 6. How can I get python indexing and slicing to work on OW_String? I
> couldn't see any information about this in the docs.

The same way you do it in Python: supply a "__getitem__" and a
"__getslice__" method.

> 7. Do I need to expose the copy constructor and assignment operator
> via Boost.Python?

You don't need assignment at all, and the copy constructor is exposed
automatically unless you have specified that your class is
noncopyable. You may want to build a copy() method, as Ralf suggests
we ought to do automatically in (I'm now
beginning to think we should just generate copy() automatically).

> 8. When I exposed the OW_String(const char*) and OW_String(char)
> constructors, python would always call OW_String(char) instead of
> OW_String(const char*). Is this intentional or a bug? I just removed
> the OW_String(char) constructor, since Python doesn't have chars
> anyway.

It's (mostly) intentional. How would you like Boost.Python to
distinguish between these two overloads?

> 9. I have an operator<< defined, but .def(str(self)) doesn't
> compile. Here's the error: no matching function for call to `
> boost::python::class_<OW_String, boost::python::detail::not_specified,
> boost::python::detail::not_specified,
> boost::python::detail::not_specified>
> ::def(boost::python::str)'

Looks like an ambiguity problem. Try .def(self_ns::str(self)) instead.

> 10. I added implicitly_convertible<const char*,OW_String>(); It
> compiled fine, but it didn't work:
> >>> import owclient
> >>> s = owclient.OW_String("a")
> >>> s.concat(owclient.OW_String("b"))
> <owclient.OW_String object at 0x817267c>
> >>> s.c_str()
> 'ab'
> >>> s.concat("c")
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> TypeError: bad argument type for built-in operation
> Any ideas why this didn't work?

Not offhand. Can you post a small test case?

                    David Abrahams
dave_at_[hidden] *

Boost list run by bdawes at, gregod at, cpdaniel at, john at