A hack to let Pyrex 0.3.x users build extension classes on Win32

Graham Fawcett gmfawcett at operamail.com
Thu Jul 4 15:13:33 EDT 2002


Hi folks,

I downloaded and am using version 0.3.2 of the fantastic Pyrex
extension language (
http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/ ) and am happily
speeding up some crucial code using this marvellous product.

However, I ran into a hitch when trying to build an extension class on
my Win32 machine: the compiler complained with "initializer not a
constant" errors. This is a known issue in Python; see the FAQ at
http://www.python.org/cgi-bin/faqw.py?req=show&file=faq03.024.htp .

So I did a very ugly little hack on the pyrexc.py script to fix the
problem. (The hacked script just runs pyrexc as usual, but then
traverses each C file that pyrexc builds and applies the advice given
in the Python FAQ.

This is a brute-force and brittle approach. I expect it will break
against a release of Pyrex > 0.3.2. (I should have taken the time to
read Greg's compiler code and fix it there, but I've a temporary
shortage of Copious Free Time.)

Here's the revised script.

#!/usr/bin/env python
#
#   Pyrex -- Main Program, Unix
#

import Pyrex.Compiler.Main
Pyrex.Compiler.Main.main(c_only = 1, use_listing_file = 0)

# ---- added by Graham Fawcett <fawcett at uwindsor.ca>
# ---- fixes "Initializer not a constant" while building DLL on
MS-Windows
# ---- http://www.python.org/cgi-bin/faqw.py?req=show&file=faq03.024.htp

HEAD_INIT = 'PyObject_HEAD_INIT(0)'
TYPESTART = 'statichere PyTypeObject __pyx_type_'
GETATTR = 'PyObject_GenericGetAttr, /*tp_getattro*/'
SETATTR = 'PyObject_GenericSetAttr, /*tp_setattro*/'
ALLOC = 'PyType_GenericAlloc, /*tp_alloc*/'
FREE = '_PyObject_Del, /*tp_free*/'
TYPEINIT ='''__pyx_type_%(typename)s.ob_type = &PyType_Type;
__pyx_type_%(typename)s.tp_getattro = PyObject_GenericGetAttr;
/*tp_getattro*/
__pyx_type_%(typename)s.tp_setattro = PyObject_GenericSetAttr;
/*tp_setattro*/
__pyx_type_%(typename)s.tp_alloc = PyType_GenericAlloc; /*tp_alloc*/
__pyx_type_%(typename)s.tp_free = _PyObject_Del; /*tp_free*/
'''
def fix_c_file(pyx_filename):
    filename = pyx_filename.split('.')[0] + '.c'
    f = open(filename, 'r')
    lines = f.readlines()
    f.close()
    lines = [line.rstrip() for line in lines]
    types = []
    f = open(filename, 'w')
    for line in lines:
        # strip the injurious assignments from the PyTypeObject def'n
        if line.startswith(HEAD_INIT):
            print >> f,  'PyObject_HEAD_INIT(NULL)'
        elif line.startswith(TYPESTART):
            typename = line[len(TYPESTART):].split(' ')[0]
            types.append(typename)
            print >> f, line
        elif line.startswith(GETATTR):
            print >> f, 'NULL,' + GETATTR.split(',')[1]
        elif line.startswith(SETATTR):
            print >> f, 'NULL,' + SETATTR.split(',')[1]
        elif line.startswith(ALLOC):
            print >> f, 'NULL,' + ALLOC.split(',')[1]
        elif line.startswith(FREE):
            print >> f, 'NULL,' + FREE.split(',')[1]
        elif line.startswith('void init') and line.endswith('(void)
{'):
            print >> f, line
            # put the assignments in the module init function
            for typename in types:
                print >> f, TYPEINIT % locals()
        else:
            pass
            print >> f, line
    f.close()

import sys
if sys.platform == 'win32':
    for pyx_filename in sys.argv[1:]:
       fix_c_file(pyx_filename)

# ---- end of addition

Best wishes,

-- Graham



More information about the Python-list mailing list