views:

291

answers:

5

Hello:

I've been looking around the internet trying to find a good step by step guide to extend Python in Windows, and I haven't been able to find something for my skill level.

let's say you have some c code that looks like this:

#include <stdio.h>
#include <math.h>

double valuex(float value, double rate,  double timex)
{
    float value;
    double rate, timex;
    return value / (double) pow ((1 + rate), (timex));
}

and you want to turn that into a Python 3 module for use on a windows (64bit if that makes a difference) system. How would you go about doing that? I've looked up SWIG and Pyrex and in both circumstances they seem geared towards the unix user. With Pyrex I am not sure if it works with Python 3.

I'm just trying to learn the basics of programing, using some practical examples.

Lastly, if there is a good book that someone can recommend for learning to extend, I would greatly appreciate it.

Thank you.

+1  A: 

A start would be the documentation Building C and C++ Extensions on Windows.

Felix Kling
A: 

Well, the easiest way to create Python plugins is to use C++ and Boost.Python. In your example, the extension module would look as simple as this:

#include <boost/python.hpp>
using namespace boost::python;

// ... your valuex function goes here ...

BOOST_PYTHON_MODULE(yourModuleName)
{
    def("valuex", valuex, "an optional documentation string");
}

Boost.Python is available on the popular operating systems and should work with Python 3, too (not tested it, though, support was added in 2009).

Regarding SWIG: It is not for Unix only. You can download precompiled Windows binaries or compile it yourself with MinGW/MSYS.

You could as well try out Cython which is said to be Python 3 compatible.

AndiDog
+1  A: 

Cython (Pyrex with a few kinks worked out and decisions made for practicality) can use one code base to make Python 2 and Python 3 modules. It's a really great choice for making libraries for 2 and 3. The user guide explains how to use it, but it doesn't demystify Windows programming or C or Python or programming in general, thought it can simplify some things for you.

SWIG can be hard to work with when you run into a problem and will not be especially conducive to creating a very native-feeling, idiomatic binding of the C you are relying on. For that, you would need to re-wrap the wrapper in Python, at which point it might have been nicer just to use Cython. It can be nice for bindings that you cannot dedicate enough work to make truly nice, and is convenient in that you can expose your API to many languages at once in it.

Mike Graham
+2  A: 

Depending on what you're trying to do, building your "extension" as a simple DLL and accessing it with ctypes could be, by far, the simplest approach.

I used your code, slightly adjusted and saved as mydll.c:

#include <stdio.h>
#include <math.h>

#define DLL_EXPORT __declspec(dllexport)
DLL_EXPORT double valuex(float value, double rate,  double timex)
    {
    float value;
    double rate, timex;
    return value / (double) pow ((1 + rate), (timex));
    }

I downloaded the Tiny C Compiler and invoked with this command.

tcc -shared mydll.c

(I believe adding -rdynamic would avoid the need to sprinkle DLL_EXPORT all over your function defs.)

This generated mydll.dll. I then ran Python:

Python 3.1.2 (r312:79149, Mar 21 2010, 00:41:52) ... on win32
>>> from ctypes import *
>>> mydll = cdll.mydll
>>> valuex = mydll.valuex
>>> valuex.argtypes = [c_float, c_double, c_double]
>>> valuex.restype = c_double
>>> valuex(1.2, 2.3, 3.4)
2.0470634033800796e-21
Peter Hansen
+1, This is how I've done it in the past. If you're doing it for performance reasons, you should be aware that ctypes does add a little overhead. This guy ran some benchmarks: http://tungwaiyip.info/blog/2009/07/16/ctype_performance_benchmark
FogleBird
@FogleBird, thanks for the link! In summary he seems to say ctypes is maybe 2-3 times slower for the calling mechanism than more direct approaches, which makes it poor for "fine-grained" work (i.e. many calls to short routines). (That's one reason I cautioned "depending on what you're trying to do".)
Peter Hansen
@peter, I tried this but sadly tcc for windows only supports 32 bit versions (at least according to the readme), which explains why I couldn't load the .dll at this line "mydll = cdll.mydll". I'm currently trying to setup Cython though, and I think I'm almost there.
JR
@JR, I used TCC for merely demonstration purposes but you can use any other compiler that works for you. You'll need a working compiler for any of the other ways of doing this anyway (maybe mingw or vc++).
Peter Hansen
A: 

At PyCon 2009, I gave a talk on how to write Python C extensions: A Whirlwind Excursion through Python C Extensions. There's nothing specific to Windows in it, but it covers the basic structure of an extension.

Ned Batchelder