[C++-sig] Re: Interest in luabind

Daniel Wallin dalwan01 at student.umu.se
Mon Jun 23 14:21:03 CEST 2003


> "Daniel Wallin" <dalwan01 at student.umu.se> writes:
>
> I wrote:
>
> >> >> In fact, the more I look at the syntax of luabind,
> the more I like.
> >> >> Using addition for policy accumulation is cool.  The
> naming of the
> >> >> policies is cool.
> >> >
> >> > It does increase compile times a bit though
> >>
> >> What, overloading '+'?  I don't think it's significant.
> >
> > I meant composing typelist's with '+' opposed to
> composing
> > the typelist manually like in BPL.
>
> I think we agree that's probably minor.

Right.

>
> >> >> >> > This doesn't increase compile times.
> >> >> >>
> >> >> >> Good.  Virtual functions come with bloat of their
> own, but that's
> >> >> >> an implementation detail which can be mitigated.
> >> >> >
> >> >> > Right. The virtual functions isn't generated in
> the
> >> >> > template, so there is very little code generated.
> >> >>
> >> >> I don't see how that's possible, but I guess I'll
> learn.
> >> >
> >> > We can generate the wrapper code in the template, and
> store
> >> > function pointers in the object instead of generating
> a
> >> > virtual function which generates the wrapper
> functions.
> >>
> >> Well, IIUC, that means you have to treat def() the same
> when it
> >> appears inside a class [...] as when it's inside a
> module [ ... ],
> >> since there's no delayed evaluation.
> >>
> >>     ah, wait: you don't use [ ... ] for class, which
> gets you off
> >>     the hook.
> >>
> >>     but what about nested classes?  Consistency would
> dictate the
> >>     use of [ ... ].
> >
> > Right, we don't have nested classes. We have thought
> about a
> > few solutions:
> >
> > class_<A>("A")
> >   .def(..)
> >   [
> >     class_<inner>("inner")
> >       .def(..)
> >   ]
> >   .def(..)
> >   ;
>
> Looks pretty!

:)

>
> > Or reusing namespace_:
> >
> >   class_<A>("A"),
> >   namespace_("A")
> >   [ class_<inner>(..) ]
> >
> > We thought that nested classes is less common than
> nested
> > namespaces.
>
> Either one works; I like the former, but I think you ought
> to be able
> to do both.

Yeah, both need really minor adjustments to the system.

>
>
> >> There is still an issue of to-python conversions for
> wrapped
> >> classes; different ones get generated depending on how
> the class is
> >> "held".  I'm not convinced that dynamically generating
> the smart
> >> pointer conversions is needed, but conversions for
> virtual function
> >> dispatching subclass may be.
> >
> > I don't understand how this has anything to do with
> ordering. Unless
> > you mean that you need to register the types before
> executing
> > python/lua code that uses them, which seems pretty
> obvious. :)
>
> It has nothing to do with ordering; I'm just thinking out
> loud about
> how much dynamic lookup is actually buying in
> Boost.Python.

Ah, ok. :)

>
> >> >> >> How do *add* a way to convert from Python type A
> to C++ type B
> >> >> >> without masking the existing conversion from
> Python type Y to C++
> >> >> >> type Z?
> >> >> >
> >> >> > I don't understand. How are B and Z related? Why
> would a
> >> >> > conversion function for B mask conversions to Z?
> >> >>
> >> >> Sorry, B==Z ;-)
> >> >
> >> > Ah, ok. Well, this isn't finished either. We have a
> >> > (unfinished) system which works like this:
> >> >
> >> > template<>
> >> > struct implicit_conversion<0, B> : from<A> {};
> >> > template<>
> >> > struct implicit_conversion<1, B> : from<Y> {};
> >> >
> >> > Of course, this has all the problems with static
> dispatch as
> >> > well..
> >>
> >> And with multiple implicit conversions being
> contributed by
> >> multiple people.  Also note that in many environments
> there's no
> >> guarantee that different extension modules won't share
> a link
> >> namespace, so you have to watch out for ODR problems.
> >
> > Right. We didn't really intend for luabind to be used in
> this way,
> > but rather for binding closed modules.
>
> I think I'm saying that on some systems (not many),
> there's no such
> thing as a "closed module".  If they're loaded in the same
> process,
> they share a link namespace :(
>
> >> > I think so too. I'm looking around in BPL's
> conversion system now
> >> > trying to understand how I incorporate it in luabind.
> >>
> >> I am not convinced I got it 100% right.  You've forced
> me to think
> >> about the issues again in a new way.  It may be that
> the best
> >> answer blends our two approaches.
> >
> > Your converter implementation with static ref's to the
> > registry entry is really clever.
>
> Thanks!
>
> > Instead of doing this we have general converters which
> is used to
> > convert all user-defined types.
>
> I have the same thing for most from_python conversions;
> the registry
> is only used as a fallback in that case.

Hm, doesn't the conversion of UDT's pass through the normal
conversion system?

>
> > To do this we need a map<..> lookup to find the
> appropriate
> > converter and this really sucks.
>
> I can't understand why you'd need that, but maybe I'm
> missing
> something.  The general mechanism in Boost.Python is that
> instance_holder::holds(type_info) will give you the
> address of the
> contained instance if it's there.

Right, we have a map<const type_info*, ..> when performing
c++ -> lua conversions. You just need to do
registered<T>::conversions.to_python(..); Correct?

>
> > As mentioned before, lua can have multiple states, so it
> would be
> > cool if the converters would be bound to the state
> somehow.
>
> Why?  It doesn't seem like it would be very useful to have
> different
> states doing different conversions.

It can be useful to be able to register different types in
different states. Otherwise class_() would register global
types and def() would register local functions. Or am I
wrong in assuming that class_<T>() instantiates
registered<T> and add's a few converters?

>
> > If so, this could never work between modules compiled
> with different
> > compilers.
>
> If they don't have compatible ABIs you don't want them to
> match
> anyway, but this is currently an area of weakness in the
> system.

Right.

>
> > So it seems to me like this feature can't be that
> useful,
> > what am I missing?
>
> Well, it's terribly useful for teams who are developing
> large
> systems.  Each individual can produce wrappers just for
> just her part
> of it, and they all interact correctly.

Right.

>
> > Anyway, I find your converter system more appealing than
> > ours. There are some issues which need to be taken care
> of;
> > We choose best match, not first match, when trying
> different
> > overloads. This means we need to keep the storage for
> the
> > converter on the stack of a function that is unaware of
> the
> > converter size (at compile time). So we need to either
> have
> > a fixed size buffer on the stack, and hope it works, or
> > allocate the storage at runtime.
>
> I would love to have best match conversion.  I was going
> to do it at
> one point, but realized eventually that users can sort the
> overloads
> so that they always work so I never bothered to code it.

Do you still think best match is worth adding, or is sorting
an acceptable solution?

>
> > For clarification:
> >
> > void dispatcher(..)
> > {
> >   *storage here*
> >   try all overloads
> >   call best overload
> > }
>
> I've already figured out how to solve this problem; if we
> can figure
> out how to share best-conversion technology I'll happily
> code it up
> ;-)

:) How would you do it? I guess you could have static
storage in the match-function and store a pointer to that in
the converter data, but that wouldn't be thread safe.

It seems to me that sharing the conversion code out of the
box is going to be hard. Perhaps we should consider
parameterizing header files?

namespace luabind
{
  #define BOOST_LANG_CONVERSION_PARAMS \
    (2, (lua_State*, int))
  #include <blabla/conversions.hpp>
}

--
Daniel Wallin




More information about the Cplusplus-sig mailing list