提交 95531c52 authored 作者: abalkin's avatar abalkin

More python 3.x fixes:

* Use PyCapsule instead of PyCObject. * Use Python 3 module initialization. * Prepend 'm' to code hash to avoid module names that start with a digit.
上级 fe50ef92
......@@ -9,7 +9,7 @@ import os
import StringIO
import sys
from itertools import izip
from six import PY3
import numpy
......@@ -17,7 +17,9 @@ if sys.version_info[:2] >= (3, 0):
import hashlib
def hash_from_code(msg):
return hashlib.md5(msg.encode()).hexdigest()
# Python 3 does not like module names that start with
# a digit.
return 'm' + hashlib.md5(msg.encode()).hexdigest()
elif sys.version_info[:2] >= (2, 5):
import hashlib
......@@ -1232,19 +1234,25 @@ class CLinker(link.Linker):
# Static methods that can run and destroy the struct built by
# instantiate.
static = """
if PY3:
static = """
int {struct_name}_executor({struct_name} *self) {{
return self->run();
}}
void {struct_name}_destructor(PyObject *capsule) {{
{struct_name} *self = ({struct_name} *)PyCapsule_GetContext(capsule);
delete self;
}}
""".format(struct_name=self.struct_name)
else:
static = """
int %(struct_name)s_executor(%(struct_name)s* self) {
return self->run();
}
void %(struct_name)s_destructor(void* executor, void* self) {
//printf("doing cleanup\\n");
//fflush(stdout);
// ((%(struct_name)s*)self)->cleanup();
// free(self);
delete ((%(struct_name)s*)self);
//printf("done cleanup\\n");
//fflush(stdout);
}
""" % dict(struct_name=self.struct_name)
......@@ -1310,7 +1318,17 @@ class CLinker(link.Linker):
print >> code, ' }'
print >> code, ' %(struct_name)s* struct_ptr = new %(struct_name)s();' % locals()
print >> code, ' struct_ptr->init(', ','.join('PyTuple_GET_ITEM(argtuple, %i)' % n for n in xrange(n_args)), ');'
print >> code, ' PyObject* thunk = PyCObject_FromVoidPtrAndDesc((void*)(&%(struct_name)s_executor), struct_ptr, %(struct_name)s_destructor);' % locals()
if PY3:
print >> code, """\
PyObject* thunk = PyCapsule_New((void*)(&{struct_name}_executor), NULL, {struct_name}_destructor);
if (thunk != NULL && PyCapsule_SetContext(thunk, struct_ptr) != 0) {{
PyErr_Clear();
Py_DECREF(thunk);
thunk = NULL;
}}
""".format(**locals())
else:
print >> code, ' PyObject* thunk = PyCObject_FromVoidPtrAndDesc((void*)(&%(struct_name)s_executor), struct_ptr, %(struct_name)s_destructor);' % locals()
print >> code, " return thunk; }"
return code.getvalue()
......
......@@ -13,7 +13,7 @@ import subprocess
import sys
import tempfile
import time
from six import b, next
from six import PY3, b, next
import distutils.sysconfig
......@@ -165,11 +165,27 @@ class DynamicModule(object):
print >> stream, "};"
def print_init(self, stream):
print >> stream, "PyMODINIT_FUNC init%s(void){" % self.name
for b in self.init_blocks:
print >> stream, ' ', b
print >> stream, ' ', ('(void) Py_InitModule("%s", MyMethods);'
% self.name)
if PY3:
print >> stream, """\
static struct PyModuleDef moduledef = {{
PyModuleDef_HEAD_INIT,
"{name}",
NULL,
-1,
MyMethods,
}};
""".format(name=self.name)
print >> stream, "PyMODINIT_FUNC PyInit_%s(void) {" % self.name
for b in self.init_blocks:
print >> stream, ' ', b
print >> stream, " PyObject *m = PyModule_Create(&moduledef);"
print >> stream, " return m;"
else:
print >> stream, "PyMODINIT_FUNC init%s(void){" % self.name
for b in self.init_blocks:
print >> stream, ' ', b
print >> stream, ' ', ('(void) Py_InitModule("%s", MyMethods);'
% self.name)
print >> stream, "}"
def add_include(self, str):
......@@ -1639,6 +1655,7 @@ class GCC_compiler(object):
if py_module:
#touch the __init__ file
open(os.path.join(location, "__init__.py"), 'w').close()
assert os.path.isfile(lib_filename)
return dlimport(lib_filename)
......
import os
import sys
from six import PY3
from theano.gof.compilelock import get_lock, release_lock
from theano import config
......@@ -38,8 +39,29 @@ def compile_cutils():
{"run_cthunk", run_cthunk, METH_VARARGS|METH_KEYWORDS,
"Run a theano cthunk."},
{NULL, NULL, 0, NULL} /* Sentinel */
};"""
if PY3:
# This is not the most efficient code, but it is written this way to highlight
# the changes needed to make 2.x code compile under python 3.
code = code.replace("<Python.h>", '"numpy/npy_3kcompat.h"', 1)
code = code.replace("PyCObject", "NpyCapsule")
code += """
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"cutils_ext",
NULL,
-1,
CutilsExtMethods,
};
PyMODINIT_FUNC
PyInit_cutils_ext(void) {
return PyModule_Create(&moduledef);
}
}
"""
else:
code += """
PyMODINIT_FUNC
initcutils_ext(void)
{
......@@ -68,7 +90,7 @@ try:
if not os.path.exists(location):
os.mkdir(location)
if not os.path.exists(os.path.join(location, '__init__.py')):
file(os.path.join(location, '__init__.py'), 'w').close()
open(os.path.join(location, '__init__.py'), 'w').close()
try:
from cutils_ext.cutils_ext import *
......
......@@ -1023,7 +1023,8 @@ static struct PyModuleDef moduledef = {
#endif
#if defined(NPY_PY3K)
#define RETVAL m
PyObject *PyInit_lazylinker_ext(void) {
PyMODINIT_FUNC
PyInit_lazylinker_ext(void) {
#else
#define RETVAL
PyMODINIT_FUNC
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论