PyRex — Python with C types
I don’t see how to put Pyrex together to existing C libraries, though.
Pyrex
A language for writing Python extension modules
What is Pyrex all about?
Pyrex is a language specially designed for writing Python extension modules.
It’s designed to bridge the gap between the nice, high-level, easy-to-use
world of Python and the messy, low-level world of C.
The fundamental nature of Pyrex can be summed up as follows: Pyrex is
Python with C data types.
Pyrex is Python: Almost any piece of Python code is also valid
Pyrex code. (There are a few limitations, but this approximation will serve
for now.) The Pyrex compiler will convert it into C code which makes equivalent
calls to the Python/C API. In this respect, Pyrex is similar to the former
Python2C project (to which I would supply a reference except that it no
longer seems to exist).
…with C data types. But Pyrex is much more than that, because
parameters and variables can be declared to have C data types. Code which
manipulates Python values and C values can be freely intermixed, with conversions
occurring automatically wherever possible. Reference count maintenance
and error checking of Python operations is also automatic, and the full
power of Python’s exception handling facilities, including the try-except
and try-finally statements, is available to you — even in the midst of
manipulating C data.
Here’s a small example showing some of what can be done. It’s a routine
for finding prime numbers. You tell it how many primes you want, and it
returns them as a Python list.
primes.pyx
1 def primes(int kmax): 2 cdef int n, k, i 3 cdef int p[1000] 4 result = [] 5 if kmax > 1000: 6 kmax = 1000 7 k = 0 8 n = 2 9 while k < kmax:10 i = 011 while i < k and n % p[i] <> 0:12 i = i + 113 if i == k:14 p[k] = n15 k = k + 116 result.append(n)17 n = n + 118 return result
You’ll see that it starts out just like a normal Python function definition,
except that the parameter kmax is declared to be of type int
. This means that the object passed will be converted to a C integer (or
a TypeError will be raised if it can’t be).
Language Details
For more about the Pyrex language, see the Language
Overview .
#include "Python.h"
static PyObject *__Pyx_UnpackItem(PyObject *, int);static int __Pyx_EndUnpack(PyObject *, int);static int __Pyx_PrintItem(PyObject *);static int __Pyx_PrintNewline(void);static void __Pyx_ReRaise(void);static void __Pyx_RaiseWithTraceback(PyObject *, PyObject *, PyObject *);static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list);static PyObject *__Pyx_GetExcValue(void);static PyObject *__Pyx_GetName(PyObject *dict, char *name);
static PyObject *__pyx_m;static PyObject *__pyx_d;static PyObject *__pyx_b;
PyObject *__pyx_f_primes(PyObject *__pyx_self, PyObject *__pyx_args); /*proto*/PyObject *__pyx_f_primes(PyObject *__pyx_self, PyObject *__pyx_args) { int __pyx_v_kmax; int __pyx_v_n; int __pyx_v_k; int __pyx_v_i; int (__pyx_v_p[1000]); PyObject *__pyx_v_result; PyObject *__pyx_r; PyObject *__pyx_1 = 0; int __pyx_2; int __pyx_3; int __pyx_4; PyObject *__pyx_5 = 0; PyObject *__pyx_6 = 0; if (!PyArg_ParseTuple(__pyx_args, "i", &__pyx_v_kmax)) return 0; __pyx_v_result = Py_None; Py_INCREF(__pyx_v_result);
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":2 */
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":3 */
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":4 */ __pyx_1 = PyList_New(0); if (!__pyx_1) goto __pyx_L1; Py_DECREF(__pyx_v_result); __pyx_v_result = __pyx_1; __pyx_1 = 0;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":5 */ __pyx_2 = (__pyx_v_kmax > 1000); if (__pyx_2) {
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":6 */ __pyx_v_kmax = 1000; goto __pyx_L2; } __pyx_L2:;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":7 */ __pyx_v_k = 0;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":8 */ __pyx_v_n = 2;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":9 */ while (1) { __pyx_L3:; __pyx_2 = (__pyx_v_k < __pyx_v_kmax); if (!__pyx_2) break;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":10 */ __pyx_v_i = 0;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":11 */ while (1) { __pyx_L5:; if (__pyx_3 = (__pyx_v_i < __pyx_v_k)) { __pyx_3 = ((__pyx_v_n % (__pyx_v_p[__pyx_v_i])) != 0); } if (!__pyx_3) break;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":12 */ __pyx_v_i = (__pyx_v_i + 1); } __pyx_L6:;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":13 */ __pyx_4 = (__pyx_v_i == __pyx_v_k); if (__pyx_4) {
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":14 */ (__pyx_v_p[__pyx_v_k]) = __pyx_v_n;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":15 */ __pyx_v_k = (__pyx_v_k + 1);
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":16 */ __pyx_1 = PyObject_GetAttrString(__pyx_v_result, "append"); if (!__pyx_1) goto __pyx_L1; __pyx_5 = PyInt_FromLong(__pyx_v_n); if (!__pyx_5) goto __pyx_L1; __pyx_6 = PyTuple_New(1); if (!__pyx_6) goto __pyx_L1; PyTuple_SET_ITEM(__pyx_6, 0, __pyx_5); __pyx_5 = 0; __pyx_5 = PyObject_CallObject(__pyx_1, __pyx_6); if (!__pyx_5) goto __pyx_L1; Py_DECREF(__pyx_6); __pyx_6 = 0; Py_DECREF(__pyx_5); __pyx_5 = 0; goto __pyx_L7; } __pyx_L7:;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":17 */ __pyx_v_n = (__pyx_v_n + 1); } __pyx_L4:;
/* "ProjectsA:Python:Pyrex:Demos:primes.pyx":18 */ Py_INCREF(__pyx_v_result); __pyx_r = __pyx_v_result; goto __pyx_L0;
__pyx_r = Py_None; Py_INCREF(__pyx_r); goto __pyx_L0; __pyx_L1:; Py_XDECREF(__pyx_1); Py_XDECREF(__pyx_5); Py_XDECREF(__pyx_6); __pyx_r = 0; __pyx_L0:; Py_DECREF(__pyx_v_result); return __pyx_r;}
static struct PyMethodDef __pyx_methods[] = { {"primes", (PyCFunction)__pyx_f_primes, METH_VARARGS, 0}, {0, 0, 0, 0}};
void initprimes(void); /*proto*/void initprimes(void) { __pyx_m = Py_InitModule4("primes", __pyx_methods, 0, 0, PYTHON_API_VERSION); __pyx_d = PyModule_GetDict(__pyx_m); __pyx_b = PyImport_AddModule("__builtin__"); PyDict_SetItemString(__pyx_d, "__builtins__", __pyx_b);}/* Runtime support code */