[Ns-developers] Status of Python bindings
Gustavo Carneiro
gjcarneiro at gmail.com
Wed May 7 10:54:01 PDT 2008
2008/5/6 Mathieu Lacage <mathieu.lacage at sophia.inria.fr>:
>
> On Tue, 2008-05-06 at 00:56 +0100, Gustavo Carneiro wrote:
>
> > > 2. Once in a while, a developer does something like ./waf
> > --scan-bindings,
> > > which calls pybindgen in gccxml mode, and outputs a
> > ns3module_generated.py
> > > file (or several files, one per module, if the generated
> > file ends up being
> > > large)
> >
> >
> > +1 to the latter option (one file per ns3 module)
> >
> > It is non-trivial work, but I can do it.
>
> +1 beer !
>
>
> > I would be fine with re-running --scan-bindings (2) regularly
> > to attempt
> > to generate the bindings for our codebase provided we can
> > agree that if
> > it fails and if you cannot fix it (because you are dead or
> > just away for
> > an extended period of time :), we can just use its output as a
> > starting
> > point and then, write the missing python code by hand. To
> > summarize, if
> > 2) works sufficiently well that the generated code is readable
> > and
> > editable and that we almost never have to hack its output, I
> > am all for
> > it because I know that, at worst, I can hack it without
> > relying on you
> > being alive.
> >
> > But of course the code will be perfectly readable and hackable.
>
> +2 beer !
>
> >
> > Only the customizations for supporting the core module, as well as
> > simulador schedule, will be hard to read, but that can't be helped.
> > If you want a nice Python API you need custom code for certain low
> > level stuff. That would be true for _any_ python binding technology
> > you decided to use.
>
> yes.
>
> >
> > As for me disappearing, Python bindings for NS-3 would be in no worse
> > shape than NS-3 core module would be if you disappeared and took all
> > that C++ template black magic with you... :-)
>
> yep.
>
>
> > Which clearly outlines the underlying C++ function and its
> > python
> > equivalent.
> >
> > If the python function name is different from the C++ one you are
> > probably doing something wrong. Different <whatever> names in Python
>
> There are some cases where you want to do that to wrap some non-trivial
> C++ APIs to python: For example, the Simulator::Schedule methods cannot
> be easily wrapped and I see, as expected, that you are using renaming
> tricks to wrap them.
>
> > and C++ will only cause confusion for NS-3 programmers, who often
> > need to switch back and forth between Python and C++ and do not want
> > to learn two similar but subtly different APIs. So I really don't
> > agree making the python name mandatory will be helpful.
>
> ok.
>
> >
> >
> >
> > Now, I do understand why you took the simpler path of avoiding
> > the
> > redundant information everywhere because the number of cases
> > where
> > CppFunctionName will be different from PyFunctionName will be
> > very small
> > but, that shortcut really does muddy the conceptual model of
> > how things
> > work.
> >
> > So, I can see a couple of ways to deal with this 'muddying':
> > a) become pedantic as suggested above at the cost of extra
> > verbosity
> > and pain
> > b) structure in the API in a different way which moves all
> > the
> > assumptions about the C++ -> python names to a single clear
> > location.
> >
> > I think that a) is really too painful so, what could b) look
> > like ?
> >
> > Bah.. you are just using the old trick of offering a worse alternative
> > as option so that the one you prefer does not seem so bad by
> > comparison... :P
>
> My boss gave me hands-on courses in rhetoric :)
>
> > But I am willing to give it a fair chance..
>
> thank you :)
>
> > .
> >
> > Here
> > is a proposal:
> >
> > # describe the C++ code we want to wrap
> > header = CppHeader ('a.h')
> > header.add_function ('CppFunctionName', return_type, args)
> > A = header.add_class ('CppClassName, ...)
> > A.add_method (...)
> > ns3 = header.add_namespace ('ns3')
> > ns3.add_function (...)
> > ns3.add_class (...)
> >
> > Since I really want PyBindGen to be applicable to pure C code as well
> > as C++, this would have to be just class Header, not CppHeader.
>
> I thought that we could have a CHeader class to mirror CppHeader for
> that case.
>
> >
> >
> >
> > # describe how to wrap the above C++ code.
> > mod = PyModule ('a')
> > mod.wrap_header (header)
> > mod.generate_output (out_file)
> >
> > Personally, I don't grok this model very well. Types and functions
> > belong to namespaces, not headers. When you are programming in C++
> > you don't think in terms of which header file each type lives in, you
> > think about namespaces. Or at least I do.
>
> I suspect that my main concern is that I have not yet been able to
> really understand the model implemented by your API which is why I have
> tried to come up with a model which made sense to me. So, I wrote a
> couple more examples attached to this email to try to get a better
> handle on the way your API is structured: feel free to add them to your
> examples directory.
>
> Thinking some more about your API, I wrote the following summary: would
> you mind point out what I misunderstood ?
>
> The Module python class represents a set of python bindings to generate
> within a top-level python module. If you write:
> mod = Module ('a')
> mod.add_ (...)
> you effectively create a python module 'a' which contains:
> - a set of python functions to wrap c++ functions
> - a set of python classes to wrap c++ classes
> - a set of python modules to wrap c++ namespaces
> - a set of python inner classes to wrap c++ inner classes
>
>
>
> Is the above paragraph correct ?
Basically is correct.
>
>
> Part of my confusion with this API might simply be that this 'Module'
> python class does not necessarily represent a single python module: it
> _can_ represent one but it can also represent a python package.
Erm.. more or less.
One toplevel Module can contain other inner submodules, which are also
Module objects. Each Module can have a parent Module or None. So what you
have in the end is a tree of Modules.
All the Modules in a tree are generated to the _same_ Python module shared
library. Although it looks like a package, in the sense that you can do
from <module> import <submodule>, they are all in the same file and
<submodule> is always present. In normal Python packages, you need to do
"import foo.bar" before you can use foo.bar; in these
modules-containing-other-modules you can "import foo" and then access
foo.bar (like, with pygtk, you can access gtk.gdk with just importing gtk).
So, there are similarities, but also some subtle differences to a real
Python package.
What should be retained is that, in terms of wrapping C++ code, you can have
a tree of Module objects. Of course these Modules are a Python centric
representation :-) But what I envision and try to support directly in
PyBindGen, because I think makes sense, is that Modules can represent C++
namespaces. A tree of C++ namespaces is mapped to a tree of modules.
Of course Modules are more generic, and you can make Python submodules for
specific groups of functions or types, if that's what you want.
> So,
> maybe the simple solution to my complaints would be to find a better
> name for that class such as 'Binding' and use it as follows:
>
> binding = Binding ('TopLevelModuleName')
> binding.add_ (...)
This is pending more discussion.
I am not sure I understand the concept of this Binding... In C++ we have a
tree of namespaces, each containing functions and types. This is a C++
model centric view. Earlier you were proposing a source header file centric
view, where you modeled the API based on which header file it is contained.
Can you help me understand this Binding class? I don't quite understand
what it tries to model...
Now, while writing the attached examples, it occured to me that a small
> set of minor syntactical changes would also improve the API:
> - add_include ('"a.h"') -> add_include ('a.h')
Agreed to add_local_include('a.h') and add_system_include('a.h') (because of
"a.h" vs <a.h>)
>
> - C = CppClass (...), add_class (C) -> C = add_cpp_class (...)
OK.
>
> - add_method (CppMethod (...)) -> add_cpp_method (...)
Agreed , but add_method(name, returntype, params) instead of add_cpp_method.
>
> - Function (return_type, name, args) -> Function (name, return_type,
> args). The same would hold for add_cpp_method, of course.
Fine.
--
Gustavo J. A. M. Carneiro
INESC Porto, Telecommunications and Multimedia Unit
"The universe is always one step beyond logic." -- Frank Herbert
More information about the Ns-developers
mailing list