[bind10-dev] direct python bindings
Jelte Jansen
jelte at isc.org
Wed Apr 14 17:24:33 UTC 2010
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hi,
in case you're not following commits closely, I committed some work on
the manual python bindings today, it's in the branch
experiments/python-bindings, and is a continuation of the work done by
Francis (thanks btw :) it has been a great help getting started)
I created them in a subdirectory src/lib/dns/python.
It's not nearly complete, I haven't done message yet, or any rdata
classes except the base Rdata (and even that one only partly, so we can
at least use RRsets, and to be honest, i'm wondering if we really need
separate classes for every rr type), but it was about time we all took a
look at it. There's also only tests for 2 of the classes, and no
api-level documentation (though rrclass_python.cc and name_python.cc do
have quite a bit of inline comments on why things are done wrt the
binding code, if you're gonna read through the code, read those first in
that order). Those tests do show how it would be used (most of the
interface is quite directly based on the c++ version, though i think we
may add more convenience python-y stuff later).
It need the python-dev package installed on your system (and there's no
configure check for that yet, if you get compilers errors because you
didn't have it you when you ran configure you might need a full clean build)
Information below is from the README in aforementioned directory, but
for your convenience i've included it in this message.
If we decide to continue with this, my next steps are to look what
bindings we need right now in our python modules and implement those
first, before finishing up the rest.
Jelte
- --
README:
This is a partial implementation of the python wrappers for isc::dns.
Currently, when compiled the module is called libdns_python. If we
decide to use it we will add a default import under lib/python/isc.
To use it from the source tree, you must add src/lib/dns/python/.libs
to your PYTHONPATH environment variable. Within python you can then use
> import libdns_python
> rrc = libdns_python.RRClass("IN")
Notes:
this implementation is far from complete; currently wrappers for the
following classes are implemented:
full (though we might add some conveniences later, like __str__):
RRType, RRClass, RRTTL, Name, and MessageRenderer
partial:
RRset (doesn't have a way to iterate over rdata yet)
Rdata (only the most basic support, you can create one from a type,
class and string, and you can convert them to text, but that's about
it).
We did not implement the buffer classes; everywhere in the API where
buffers are used, you can pass a bytearray object.
The 'main' module is defined in libdns_python.cc.
There is a libdns_python_common.[cc|h] for helper functions.
Implementation notes:
Writing wrappers for a lot of classes is mostly a case of repetition.
There are a lot of things one must do, and that is why nearly everyone
immediately and continually has the urge to make generators for this.
We have added a little more documentation than is strictly necessary to
rrclass.h, for reference to new readers.
To keep it maintainable as the original API changes, we use two
techniques;
1. Full unittests. Or at least as full as possible. All unittests from
the C++ code will also appear in the python wrapper tests (currently
only done for rrtype and rrset as far as implemented), so if we
forget to update a wrapper our tests should fail.
2. Structure. I have tried to structure the wrapper files as much as
possible, see below.
Structure:
Since we are moving a lot of wrappers into one module, the specific
classes are split over several files, each one having the name of the
original header file they are wrapping (e.g. the wrapper for name.h
becomes name_python.cc).
At the top we first declare any exceptions, constants, and enums. These
are all called po_<C++-name> (the actual python name will be set once
they are added to the module in the module inialization function).
Each class needs a struct that contains a pointer to an instance of the
object (and any helper data). We call these structs s_<C++ class name>.
Then we declare (but not define!) all methods we will export to
python. These are named <C++ class name>_<C++ method name>.
We will also need an _init and _destroy function for all of these.
After the function declarations we define the method array; this
contains the name of the methods as they appear in python, the wrapping
function here, and documentation strings.
Next is the type description; this is used for the wrapper code to
convert native classes from and to python objects, and defines
type-specific pointers (for instance to the method table mentioned above,
but also to a __str__ function should one be defined, how the object
should behave when it is used as a Sequence, etc.). For most classes,
almost all values here shall be NULL.
This has the name <lowercase C++ class name>_type.
After that we define the exported functions we defined earlier. In some
cases these need the type we just defined, and the type needed the
function names, so for consistency, all functions are defined after,
but declared before the type.
This is repeated for every class we export.
Finally we define the function to add the class, constants, exceptions,
and enums to the module. This function is called from the init function
in libdns_python.cc, has the name
initModulePart_<c++ class name>, returns a boolean
(true on success, false on failure), and takes the module as a
PyObject*.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAkvF+lEACgkQ4nZCKsdOncUVOgCgkw+UIfqSlX2HzkKaR3uRlVhS
fgMAoIwQc3Jk8ePiNYjPWugeemV3Fsur
=u/37
-----END PGP SIGNATURE-----
More information about the bind10-dev
mailing list