[C++-sig] Interface design.
Nicodemus
nicodemus at globalite.com.br
Tue Apr 22 18:24:44 CEST 2003
tALSit de CoD wrote:
> At 10:27 22/04/2003 -0400, you wrote:
>
>> tALSit de CoD <talsit at talsit.org> writes:
>>
>> Or you can actually break your extension module into separate
>> extension modules. It's a little-known and underutilized feature of
>> Boost.Python that component-based development is supported.
>
>
> But can you have nested modules? As in:
>
> BOOST_PYTHON_MODULE (kikura) {
> BOOST_PYTHON_MODULE (kikuraCore) {
> ... stuff ...
> }
> BOOST_PYTHON_MODULE (kikuraNode) {
> ... stuff ...
> }
> }
>
> Or would you need something like so:
>
> BOOST_PYTHON_MODULE (kikuraCore) {
> ... stuff ...
> }
> BOOST_PYTHON_MODULE (kikuraNode) {
> ... stuff ...
> }
>
> In this case (or both really), how would you import the modules from
> python? I'm not too sure how python looks for dynamic libs, but would
> you have to put each module in a separate dynamic library, and then
> call from python:
>
> import kikuraCore
> import kikuraNode
>
> ?
>
> For now, I'll be using the "unpreferred" approach to splitting up the
> thingy, as long as it works.
>
> Cheers!
Hi!
Suppose you want to have a top level package in python named kikura,
with two sub-modules, core and node, so that a user uses your package
like this:
import kikura.core
import kikura.node
kikura.core.Foo()
You can acomplish this generating the two sub-modules (core and node)
using Boost.Python, like any other module:
// file core.cpp
BOOST_PYTHON_MODULE(core)
{
...
}
// file node.cpp
BOOST_PYTHON_MODULE(node)
{
...
}
And creating the following directory structure:
/kikura
__init__.py
core.pyd
node.pyd
And that's it (the file __init__.py indicates that the directory is a
package. It can be empty, but it can be useful to provide a more
friendly interface for your users. See below).
I suggest that you name your bindings _core and _node, thought, and make
the sub-modules *python* modules which import the funcionality of the
bindings, like so:
/kikura
__init__.py
/core
__init__.py
_core.pyd
/node
__init__.py
_node.pyd
with /kikura/core/__init__.py contains the statement "from _core import
*". The same for the node package. Why do it like this? Well, because
then you can easily implement some things in python in a way that is
transparent for the user (I am assuming here that you're developing this
library). Suppose you want to add a new utility function into the core
package, made in python. You just create a file "foo.py" and put it
inside /kikura/core, and add this line to its __init__.py:
from foo import util_function, other_function
and your users will access it like so:
import kikura.core
kikura.core.util_function(10)
Back to the compilation time issue, notice that you don't have to write
all class_ declarations inside the BOOST_PYTHON_MODULE macro directly,
you can split them in any number of files you like. For example:
// file Foo.cpp
#include <kikura/Foo.h>
void export_foo()
{
class_<Foo>()...
}
// file Bar.cpp
#include <kikura/Bar.h>
void export_bar()
{
class_<Bar>()...
}
// file core.cpp
void export_foo();
void export_bar();
BOOST_PYTHON_MODULE(core)
{
export_foo();
export_bar();
}
This will take longer to compile than a single file (because the
Boost.Python headers must be compiled for each cpp), but if your
developing the library this is a big help, because a change in a header
doesn't mean the entire bindings will have to be recompiled.
Hope that helps,
Nicodemus.
More information about the Cplusplus-sig
mailing list