Extensions

Extending Python with D

We can implement python modules in D. This involves generating shared libraries (handled by CeleriD).

Module basics

The most minimal working Pyd module looks something like this:

import pyd.pyd;

extern (C) void PydMain() {
    // any calls to def MUST occur here, before module_init()
    module_init();
    // any calls to wrap_class MUST occur here, after module_init()
}

line 1 imports the pyd module, which imports all of the necessary components of Pyd.

The PydMain function is called when the module is imported by Python. You will call most of Pyd's API from here. At the very least, PydMain must contain a call to module_init. The module_init function has the following form:

PyObject* module_init(string docstring="");

It does little more than call Py_InitModule and return the new module object. This object is also available via the Pyd_Module_p property once you've called module_init.

Due to the way in which Pyd implements function and class wrapping, any calls to def must occur before the call to module_init, and any calls to wrap_class must occur after the call. I know this seems like a rather arbitrary rule, but it is important. Calls to def in the wrong place will simply be ignored, and calls to wrap_class in the wrong place will throw an assert.

PydMain will catch any D exception that is thrown from inside it, and safely pass that exception to Python.

import pyd.pyd;
import std.stdio;

void hello_func() {
    writefln("Hello, world!");
}

extern (C) void PydMain() {
    def!(hello_func)();
    module_init();
}

setup.py:

from celerid.support import setup, Extension

projName = 'hello'

setup(
    name=projName,
    version='0.1',
    ext_modules=[
    Extension(projName, srcs=['hello.d'],
        build_deimos=True,
        d_lump=True
        )
    ],
) 

Loaded and used in Python:

>>> import testdll
>>> testdll.hello_func()
Hello, world!