Embedding Python in D

A D program with embedded python might look like

module hello;

import std.stdio;
import pyd.pyd, pyd.embedded;

shared static this() {
    py_init();
}

void main() {
    writeln(py_eval!string("'1 + %s' % 2"));
}
Some Notes:
  • you must call py_init to initialize the python interpreter before making any calls to python.
  • pyd.embedded contains some goodies for calling python from D code
  • it’s even possible to expose D functions to python, then invoke them in python code in D code! (see examples/pyind)

Once again, we use distutils to compile this code using the special command pydexe:

from pyd.support import setup, Extension, pydexe_sanity_check

pydexe_sanity_check()
projName = 'hello'
setup(
    name=projName,
    version='1.0',
    ext_modules=[
        Extension(projName, ['hello.d'],
            build_deimos=True, d_lump=True
        )
    ],
)
$ python setup.py install
$ ./hello
1 + 2

InterpContext

One of the goodies in pyd.embedded is InterpContext - a class that wraps a python scope and provides some conveniences for data transfer:

module interpcontext;

import std.stdio;
import pyd.pyd, pyd.embedded;

shared static this() {
    py_init();
}

void main() {
    auto context = new InterpContext();
    context.a = 2;
    context.py_stmts("print ('1 + %s' % a)");
}

Miscellaneous

call stack is not deep enough

Certain python modules (i.e. inspect) expect python to have a nonempty call stack. This seems not to be the case in embedded python. To work around this, use InterpContext.pushDummyFrame:

context.pushDummyFrame();
py_stmts("import inspect");
context.popDummyFrame();