#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import os, sys, platform, shutil, _jcc
from cpp import PRIMITIVES, INDENT, HALF_INDENT
from cpp import cppname, cppnames, typename
from cpp import line, signature, find_method, split_pkg, sort
from cpp import Modifier, Class, Method
from _jcc import findClass
from config import INCLUDES, CFLAGS, DEBUG_CFLAGS, LFLAGS, SHARED
try:
from cpp import ParameterizedType, TypeVariable
except ImportError:
pass
python_ver = '%d.%d.%d' %(sys.version_info[0:3])
if python_ver < '2.4':
from sets import Set as set
RESULTS = { 'boolean': 'Py_RETURN_BOOL(%s);',
'byte': 'return PyInt_FromLong(%s);',
'char': 'return PyUnicode_FromUnicode((Py_UNICODE *) &%s, 1);',
'double': 'return PyFloat_FromDouble((double) %s);',
'float': 'return PyFloat_FromDouble((double) %s);',
'int': 'return PyInt_FromLong((long) %s);',
'long': 'return PyLong_FromLongLong((PY_LONG_LONG) %s);',
'short': 'return PyInt_FromLong((long) %s);',
'java.lang.String': 'return j2p(%s);' }
CALLARGS = { 'boolean': ('O', '(%s ? Py_True : Py_False)', False),
'byte': ('O', 'PyInt_FromLong(%s)', True),
'char': ('O', 'PyUnicode_FromUnicode((Py_UNICODE *) &%s, 1)', True),
'double': ('d', '(double) %s', False),
'float': ('f', '(float) %s', False),
'int': ('i', '(int) %s', False),
'long': ('L', '(long long) %s', False),
'short': ('i', '(int) %s', False),
'java.lang.String': ('O', 'env->fromJString((jstring) %s, 0)', True) }
def parseArgs(params, current, generics):
def signature(cls):
array = ''
while cls.isArray():
array += '['
cls = cls.getComponentType()
clsName = cls.getName()
if cls.isPrimitive():
return array + PRIMITIVES[clsName]
if clsName == 'java.lang.String':
return array + 's'
if clsName == 'java.lang.Object':
return array + 'o'
if generics and cls.getTypeParameters():
return array + 'K'
else:
return array + 'k'
def checkarg(cls):
while cls.isArray():
cls = cls.getComponentType()
if (cls.isPrimitive() or
cls.getName() in ('java.lang.String', 'java.lang.Object')):
return ''
return ', %s::initializeClass' %(typename(cls, current, False))
def callarg(cls, i):
if generics:
while cls.isArray():
cls = cls.getComponentType()
if cls.getTypeParameters():
ns, sep, n = rpartition(typename(cls, current, False), '::')
return ', &a%d, &p%d, %s%st_%s::parameters_' %(i, i, ns, sep, n)
return ', &a%d' %(i)
return (''.join([signature(param) for param in params]),
''.join([checkarg(param) for param in params]),
''.join([callarg(params[i], i) for i in xrange(len(params))]))
def declareVars(out, indent, params, current, generics, typeParams):
for i in xrange(len(params)):
param = params[i]
line(out, indent, '%s a%d%s;',
typename(param, current, False), i,
not param.isPrimitive() and '((jobject) NULL)' or '')
if generics:
while param.isArray():
param = param.getComponentType()
if param.getTypeParameters():
line(out, indent, 'PyTypeObject **p%d;', i)
typeParams.add(i)
def construct(out, indent, cls, inCase, constructor, names, generics):
if inCase:
line(out, indent, '{')
indent += 1
params = constructor.getParameterTypes()
if generics:
typeParams = set()
else:
typeParams = None
count = len(params)
declareVars(out, indent, params, cls, generics, typeParams)
line(out, indent, '%s object((jobject) NULL);', cppname(names[-1]))
line(out)
if count:
line(out, indent, 'if (!parseArgs(args, "%s"%s%s))',
*parseArgs(params, cls, generics))
line(out, indent, '{')
indent += 1
line(out, indent, 'INT_CALL(object = %s(%s));',
cppname(names[-1]), ', '.join(['a%d' %(i) for i in xrange(count)]))
line(out, indent, 'self->object = object;')
if inCase:
line(out, indent, 'break;')
if count:
indent -= 1
line(out, indent, '}')
if inCase:
indent -= 1
line(out, indent, '}')
def rpartition(string, sep):
if python_ver >= '2.5.0':
return string.rpartition(sep)
else:
parts = split_pkg(string, sep)
if len(parts) == 1:
return ('', '', parts[0])
return (parts[0], sep, parts[1])
def fieldValue(cls, value, fieldType):
if fieldType.isArray():
fieldType = fieldType.getComponentType()
if fieldType.isArray():
result = 'JArray<jobject>(%s->this$).wrap(NULL)'
elif fieldType.isPrimitive():
result = '%s->wrap()'
elif fieldType.getName() == 'java.lang.String':
result = 'JArray<jstring>(%s->this$).wrap()'
else:
parts = rpartition(typename(fieldType, cls, False), '::')
result = 'JArray<jobject>(%%s->this$).wrap(%s%st_%s::wrap_jobject)' %(parts)
elif fieldType.getName() == 'java.lang.String':
result = 'j2p(*%s)'
elif not fieldType.isPrimitive():
parts = rpartition(typename(fieldType, cls, False), '::')
result = '%s%st_%s::wrap_Object(*%%s)' %(parts)
else:
return value
return result %(value)
def returnValue(cls, returnType, value, genericRT=None, typeParams=None):
result = RESULTS.get(returnType.getName())
if result:
return result %(value)
if returnType.isArray():
returnType = returnType.getComponentType()
depth = 1
while returnType.isArray():
returnType = returnType.getComponentType()
depth += 1
if depth > 1:
return 'return JArray<jobject>(%s.this$).wrap(NULL);' %(value)
elif returnType.isPrimitive():
return 'return %s.wrap();' %(value)
elif returnType.getName() == 'java.lang.String':
return 'return JArray<jstring>(%s.this$).wrap();' %(value)
ns, sep, n = rpartition(typename(returnType, cls, False), '::')
return 'return JArray<jobject>(%s.this$).wrap(%s%st_%s::wrap_jobject);' %(value, ns, sep, n)
ns, sep, n = rpartition(typename(returnType, cls, False), '::')
if genericRT is not None:
if ParameterizedType.instance_(genericRT):
genericRT = ParameterizedType.cast_(genericRT)
clsArgs = []
for clsArg in genericRT.getActualTypeArguments():
if Class.instance_(clsArg):
clsNames = Class.cast_(clsArg).getName().split('.')
clsArg = '&%s::%s$$Type' %('::'.join(cppnames(clsNames[:-1])), cppname(clsNames[-1]))
clsArgs.append(clsArg)
elif TypeVariable.instance_(clsArg):
gd = TypeVariable.cast_(clsArg).getGenericDeclaration()
if Class.instance_(gd):
i = 0
for clsParam in gd.getTypeParameters():
if clsArg == clsParam:
clsArgs.append('self->parameters[%d]' %(i))
break
i += 1
else:
break
else:
break
else:
break
else:
return 'return %s%st_%s::wrap_Object(%s, %s);' %(ns, sep, n, value, ', '.join(clsArgs))
elif TypeVariable.instance_(genericRT):
gd = TypeVariable.cast_(genericRT).getGenericDeclaration()
i = 0
if Class.instance_(gd):
for clsParam in gd.getTypeParameters():
if genericRT == clsParam:
return 'return self->parameters[%d] != NULL ? wrapType(self->parameters[%d], %s.this$) : %s%st_%s::wrap_Object(%s);' %(i, i, value, ns, sep, n, value)
i += 1
elif Method.instance_(gd):
for clsParam in gd.getTypeParameters():
if genericRT == clsParam and i in typeParams:
return 'return p%d != NULL && p%d[0] != NULL ? wrapType(p%d[0], %s.this$) : %s%st_%s::wrap_Object(%s);' %(i, i, i, value, ns, sep, n, value)
i += 1
return 'return %s%st_%s::wrap_Object(%s);' %(ns, sep, n, value)
def call(out, indent, cls, inCase, method, names, cardinality, isExtension,
generics):
if inCase:
line(out, indent, '{')
indent += 1
name = method.getName()
modifiers = method.getModifiers()
params = method.getParameterTypes()
returnType = method.getReturnType()
if generics:
genericRT = method.getGenericReturnType()
typeParams = set()
else:
genericRT = None
typeParams = None
count = len(params)
declareVars(out, indent, params, cls, generics, typeParams)
returnName = returnType.getName()
if returnName != 'void':
line(out, indent, '%s result%s;',
typename(returnType, cls, False),
not returnType.isPrimitive() and '((jobject) NULL)' or '')
result = 'result = '
else:
result = ''
if cardinality and (count or not inCase):
s = cardinality > 1 and 's' or ''
line(out)
if isExtension and name == 'clone' and Modifier.isNative(modifiers):
line(out, indent, 'if (arg)')
else:
line(out, indent, 'if (!parseArg%s(arg%s, "%s"%s%s))',
s, s, *parseArgs(params, cls, generics))
line(out, indent, '{')
indent += 1
name = cppname(name)
if Modifier.isStatic(modifiers):
line(out, indent, 'OBJ_CALL(%s%s::%s(%s));',
result, '::'.join(cppnames(names)), name,
', '.join(['a%d' %(i) for i in xrange(count)]))
else:
line(out, indent, 'OBJ_CALL(%sself->object.%s(%s));',
result, name, ', '.join(['a%d' %(i) for i in xrange(count)]))
if isExtension and name == 'clone' and Modifier.isNative(modifiers):
line(out)
line(out, indent, '%s object(result.this$);', typename(cls, cls, False))
line(out, indent, 'if (PyObject_TypeCheck(arg, &FinalizerProxy$$Type) &&')
line(out, indent, ' PyObject_TypeCheck(((t_fp *) arg)->object, self->ob_type))')
line(out, indent, '{')
line(out, indent + 1, 'PyObject *_arg = ((t_fp *) arg)->object;')
line(out, indent + 1, '((t_JObject *) _arg)->object = object;')
line(out, indent + 1, 'Py_INCREF(_arg);')
line(out, indent + 1, 'object.pythonExtension((jlong) (Py_intptr_t) (void *) _arg);')
line(out, indent + 1, 'Py_INCREF(arg);')
line(out, indent + 1, 'return arg;')
line(out, indent, '}')
line(out, indent, 'return PyErr_SetArgsError("%s", arg);' %(name))
elif returnName != 'void':
line(out, indent, returnValue(cls, returnType, 'result',
genericRT, typeParams))
else:
line(out, indent, 'Py_RETURN_NONE;')
if cardinality and (count or not inCase):
indent -= 1
line(out, indent, '}')
if inCase:
indent -= 1
line(out, indent, '}')
def methodargs(methods, superMethods):
if len(methods) == 1 and methods[0].getName() not in superMethods:
count = len(methods[0].getParameterTypes())
if count == 0:
return '', '', 0
elif count == 1:
return ', PyObject *arg', ', arg', 1
return ', PyObject *args', ', args', 2
def jniname(cls):
if cls.isPrimitive():
name = cls.getName()
if name != 'void':
name = 'j' + name
else:
name = 'jobject'
return name
def jniargs(params):
count = len(params)
decls = ', '.join(['%s a%d' %(jniname(params[i]), i)
for i in xrange(count)])
if decls:
return ', ' + decls
return ''
def extension(env, out, indent, cls, names, name, count, method, generics):
line(out, indent, 'jlong ptr = jenv->CallLongMethod(jobj, %s::mids$[%s::mid_pythonExtension_%s]);',
cppname(names[-1]), cppname(names[-1]), env.strhash('()J'))
line(out, indent, 'PyObject *obj = (PyObject *) (Py_intptr_t) ptr;')
if name == 'pythonDecRef':
line(out)
line(out, indent, 'if (obj != NULL)')
line(out, indent, '{')
line(out, indent + 1, 'jenv->CallVoidMethod(jobj, %s::mids$[%s::mid_pythonExtension_%s], (jlong) 0);',
cppname(names[-1]), cppname(names[-1]), env.strhash('(J)V'))
line(out, indent + 1, 'env->finalizeObject(jenv, obj);')
line(out, indent, '}')
return
line(out, indent, 'PythonGIL gil(jenv);')
returnType = method.getReturnType()
returnName = returnType.getName()
if returnName != 'void':
line(out, indent, '%s value%s;',
typename(returnType, cls, False),
not returnType.isPrimitive() and '((jobject) NULL)' or '')
sigs = []
decrefs = []
args = []
i = 0
for param in method.getParameterTypes():
typeName = param.getName()
if typeName in CALLARGS:
sig, code, decref = CALLARGS[typeName]
elif param.isArray():
param = param.getComponentType()
if param.isPrimitive():
code = 'JArray<j%s>(%%s).wrap()' %(param.getName())
elif param.isArray():
code = 'JArray<jobject>(%s).wrap(NULL)'
elif param.getName() == 'java.lang.String':
code = 'JArray<jstring>(%s).wrap()'
else:
parts = rpartition(typename(param, cls, False), '::')
code = 'JArray<jobject>(%%s).wrap(%s%st_%s::wrap_jobject)' %(parts)
sig, decref = 'O', True
elif param.getName() == 'java.lang.String':
sig, code, decref = 'O', 'j2p(%%s))', True
else:
parts = rpartition(typename(param, cls, False), '::')
sig, code, decref = 'O', '%s%st_%s::wrap_Object(%s%s%s(%%s))' %(parts*2), True
if sig == 'O':
line(out, indent, 'PyObject *o%d = %s;', i, code %('a%d' %(i)))
args.append('o%d' %(i))
else:
args.append(code %('a%d' %(i)))
sigs.append(sig)
decrefs.append(decref)
i += 1
args = ', '.join(args)
if args:
args = ', ' + args
line(out, indent, 'PyObject *result = PyObject_CallMethod(obj, "%s", "%s"%s);',
name, ''.join(sigs), args)
i = 0
for decref in decrefs:
if decref:
line(out, indent, 'Py_DECREF(o%d);', i)
i += 1
line(out, indent, 'if (!result)')
line(out, indent + 1, 'throwPythonError();')
if returnName == 'void':
line(out, indent, 'else')
line(out, indent + 1, 'Py_DECREF(result);')
else:
signature, check, x = parseArgs([returnType], cls, False)
line(out, indent, 'else if (parseArg(result, "%s"%s, &value))',
signature, check)
line(out, indent, '{')
line(out, indent + 1, 'throwTypeError("%s", result);', name)
line(out, indent + 1, 'Py_DECREF(result);')
line(out, indent, '}')
line(out, indent, 'else')
line(out, indent, '{')
if not returnType.isPrimitive():
line(out, indent + 1, 'jobj = jenv->NewLocalRef(value.this$);')
line(out, indent + 1, 'Py_DECREF(result);')
if returnType.isPrimitive():
line(out, indent + 1, 'return value;')
else:
line(out, indent + 1, 'return jobj;')
line(out, indent, '}')
line(out)
if returnType.isPrimitive():
line(out, indent, 'return (j%s) 0;', returnName)
else:
line(out, indent, 'return (jobject) NULL;')
def python(env, out_h, out, cls, superCls, names, superNames,
constructors, methods, protectedMethods, fields, instanceFields,
mapping, sequence, rename, declares, typeset, moduleName, generics):
line(out_h)
line(out_h, 0, '#include <Python.h>')
line(out_h)
indent = 0
for name in names[:-1]:
line(out_h, indent, 'namespace %s {', cppname(name))
indent += 1
line(out_h, indent, 'extern PyTypeObject %s$$Type;', names[-1])
if generics:
clsParams = cls.getTypeParameters()
else:
clsParams = None
line(out_h)
line(out_h, indent, 'class t_%s {', names[-1])
line(out_h, indent, 'public:')
line(out_h, indent + 1, 'PyObject_HEAD')
line(out_h, indent + 1, '%s object;', cppname(names[-1]))
if clsParams:
line(out_h, indent + 1, 'PyTypeObject *parameters[%d];', len(clsParams))
line(out_h, indent + 1, 'static PyTypeObject **parameters_(t_%s *self)',
cppname(names[-1]))
line(out_h, indent + 1, '{')
line(out_h, indent + 2, 'return (PyTypeObject **) &(self->parameters);')
line(out_h, indent + 1, '}')
line(out_h, indent + 1, 'static PyObject *wrap_Object(const %s&);',
cppname(names[-1]))
if clsParams:
line(out_h, indent + 1, 'static PyObject *wrap_Object(const %s&, %s);',
cppname(names[-1]),
', '.join(['PyTypeObject *'] * len(clsParams)))
line(out_h, indent + 1, 'static PyObject *wrap_jobject(const jobject&);')
line(out_h, indent + 1, 'static void install(PyObject *module);')
line(out_h, indent + 1, 'static void initialize(PyObject *module);')
line(out_h, indent, '};')
iterator = findClass('java/util/Iterator')
enumeration = findClass('java/util/Enumeration')
while indent:
indent -= 1
line(out_h, indent, '}')
line(out)
line(out, 0, '#include "structmember.h"')
line(out, 0, '#include "functions.h"')
line(out, 0, '#include "macros.h"')
for inner in cls.getDeclaredClasses():
if inner in typeset and not inner in declares:
if Modifier.isStatic(inner.getModifiers()):
line(out, 0, '#include "%s.h"',
inner.getName().replace('.', '/'))
for method in methods:
if method.getName() == 'pythonExtension':
isExtension = True
break
else:
isExtension = False
line(out)
indent = 0
for name in names[:-1]:
line(out, indent, 'namespace %s {', cppname(name))
indent += 1
line(out, indent, 'static PyObject *t_%s_cast_(PyTypeObject *type, PyObject *arg);', names[-1])
line(out, indent, 'static PyObject *t_%s_instance_(PyTypeObject *type, PyObject *arg);', names[-1])
if constructors:
line(out, indent, 'static int t_%s_init_(t_%s *self, PyObject *args, PyObject *kwds);', names[-1], names[-1])
constructorName = 't_%s_init_' %(names[-1])
else:
constructorName = 'abstract_init'
if superCls:
superMethods = set([method.getName()
for method in superCls.getMethods()])
else:
superMethods = ()
allMethods = {}
extMethods = {}
propMethods = {}
if methods:
for method in methods:
modifiers = method.getModifiers()
name = method.getName()
params = method.getParameterTypes()
superMethod = None
isNative = Modifier.isNative(modifiers)
isStatic = Modifier.isStatic(modifiers)
if (isExtension and not isStatic and superCls and isNative):
superMethod = find_method(superCls, name, params)
if isExtension and isNative and not isStatic:
extMethods.setdefault(name, []).append(method)
if superMethod or not (isExtension and isNative and not isStatic):
if isStatic:
if name in allMethods:
if Modifier.isStatic(allMethods[name][0].getModifiers()):
allMethods[name].append(method)
elif name + '_' in allMethods:
allMethods[name + '_'].append(method)
else:
print >>sys.stderr, " Warning: renaming static method '%s' on class %s to '%s_' since it is shadowed by non-static method of same name." %(name, '.'.join(names), name)
allMethods[name + '_'] = [method]
else:
allMethods[name] = [method]
else:
if name in allMethods:
if Modifier.isStatic(allMethods[name][0].getModifiers()):
print >>sys.stderr, " Warning: renaming static method '%s' on class %s to '%s_' since it is shadowed by non-static method of same name." %(name, '.'.join(names), name)
allMethods[name + '_'] = allMethods[name]
allMethods[name] = [method]
else:
allMethods[name].append(method)
else:
allMethods[name] = [method]
if not (isExtension and isNative):
nameLen = len(name)
paramsLen = len(params)
if nameLen > 3 and paramsLen == 0 and name.startswith('get'):
propMethods.setdefault(name[3].lower() + name[4:],
[]).append(method)
elif nameLen > 3 and paramsLen == 1 and name.startswith('set'):
propMethods.setdefault(name[3].lower() + name[4:],
[]).append(method)
elif nameLen > 2 and paramsLen == 0 and name.startswith('is'):
propMethods.setdefault(name[2].lower() + name[3:],
[]).append(method)
properties = set([name for name in propMethods.iterkeys()
if name not in allMethods])
propMethods = [(name, propMethods[name]) for name in properties]
sort(propMethods, key=lambda x: x[0])
extMethods = extMethods.items()
sort(extMethods, key=lambda x: x[0])
allMethods = allMethods.items()
sort(allMethods, key=lambda x: x[0])
iteratorMethod = None
iteratorExt = False
nextMethod = None
nextExt = False
nextElementMethod = None
nextElementExt = False
mappingMethod = None
if mapping:
mappingName, mappingSig = mapping.split(':')
sequenceLenMethod = None
sequenceGetMethod = None
if sequence:
sequenceLenName, sequenceLenSig = sequence[0].split(':')
sequenceGetName, sequenceGetSig = sequence[1].split(':')
for name, methods in allMethods:
args, x, cardinality = methodargs(methods, superMethods)
sort(methods, key=lambda x: len(x.getParameterTypes()))
method = methods[0]
modifiers = method.getModifiers()
if name == 'iterator' and iteratorMethod is None:
if (not method.getParameterTypes() and
iterator.isAssignableFrom(method.getReturnType())):
iteratorMethod = method
elif name == 'next' and nextMethod is None:
if (not method.getParameterTypes() and
not method.getReturnType().isPrimitive()):
nextMethod = method
elif name == 'nextElement' and nextElementMethod is None:
if (not method.getParameterTypes() and
not method.getReturnType().isPrimitive()):
nextElementMethod = method
elif mapping and name == mappingName and mappingMethod is None:
if signature(method) == mappingSig:
mappingMethod = (method, cardinality)
elif sequence and name == sequenceLenName and sequenceLenMethod is None:
if signature(method) == sequenceLenSig:
sequenceLenMethod = (method, cardinality)
elif sequence and name == sequenceGetName and sequenceGetMethod is None:
if signature(method) == sequenceGetSig:
sequenceGetMethod = (method, cardinality)
elif isExtension and name == 'clone' and Modifier.isNative(modifiers):
args, x, cardinality = ', PyObject *arg', ', arg', 1
if Modifier.isStatic(modifiers):
line(out, indent, 'static PyObject *t_%s_%s(PyTypeObject *type%s);',
names[-1], name, args)
else:
line(out, indent, 'static PyObject *t_%s_%s(t_%s *self%s);',
names[-1], name, names[-1], args)
for name, methods in extMethods:
args, x, cardinality = methodargs(methods, superMethods)
sort(methods, key=lambda x: len(x.getParameterTypes()))
method = methods[0]
modifiers = method.getModifiers()
if name == 'iterator' and iteratorMethod is None:
if (not method.getParameterTypes() and
iterator.isAssignableFrom(method.getReturnType())):
iteratorMethod = method
iteratorExt = True
elif name == 'next' and nextMethod is None:
if (not method.getParameterTypes() and
not method.getReturnType().isPrimitive()):
nextMethod = method
nextExt = True
elif name == 'nextElement' and nextElementMethod is None:
if (not method.getParameterTypes() and
not method.getReturnType().isPrimitive()):
nextElementMethod = method
nextElementExt = True
if isExtension:
count = 0
for name, methods in extMethods:
for method in methods:
line(out, indent,
'static %s JNICALL t_%s_%s%d(JNIEnv *jenv, jobject jobj%s);',
jniname(method.getReturnType()), names[-1], name, count,
jniargs(method.getParameterTypes()))
count += 1
line(out, indent, 'static PyObject *t_%s_get__self(t_%s *self, void *data);', names[-1], names[-1])
if instanceFields:
for field in instanceFields:
fieldName = field.getName()
if fieldName not in properties:
line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data);',
names[-1], fieldName, names[-1])
if not Modifier.isFinal(field.getModifiers()):
line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data);',
names[-1], field.getName(), names[-1])
line(out)
for fieldName, methods in propMethods:
getter = False
setter = False
for method in methods:
methodName = method.getName()
if not getter and (methodName.startswith('get') or
methodName.startswith('is')):
getter = True
line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data);',
names[-1], fieldName, names[-1])
elif not setter and methodName.startswith('set'):
setter = True
line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data);',
names[-1], fieldName, names[-1])
if clsParams:
line(out, indent, 'static PyObject *t_%s_get__parameters_(t_%s *self, void *data);', names[-1], names[-1])
if instanceFields or propMethods or isExtension or clsParams:
line(out, indent, 'static PyGetSetDef t_%s__fields_[] = {', names[-1])
for field in instanceFields:
fieldName = field.getName()
if fieldName not in properties:
if Modifier.isFinal(field.getModifiers()):
line(out, indent + 1, 'DECLARE_GET_FIELD(t_%s, %s),',
names[-1], fieldName)
else:
line(out, indent + 1, 'DECLARE_GETSET_FIELD(t_%s, %s),',
names[-1], fieldName)
for fieldName, methods in propMethods:
getter = False
setter = False
for method in methods:
methodName = method.getName()
if not getter and (methodName.startswith('get') or
methodName.startswith('is')):
getter = True
elif not setter and methodName.startswith('set'):
setter = True
if getter and setter:
op = 'GETSET'
elif getter:
op = 'GET'
elif setter:
op = 'SET'
line(out, indent + 1, 'DECLARE_%s_FIELD(t_%s, %s),',
op, names[-1], fieldName)
if isExtension:
line(out, indent + 1, 'DECLARE_GET_FIELD(t_%s, self),', names[-1])
if clsParams:
line(out, indent + 1, 'DECLARE_GET_FIELD(t_%s, parameters_),',
names[-1])
line(out, indent + 1, '{ NULL, NULL, NULL, NULL, NULL }')
line(out, indent, '};')
line(out)
line(out, indent, 'static PyMethodDef t_%s__methods_[] = {', names[-1])
line(out, indent + 1,
'DECLARE_METHOD(t_%s, cast_, METH_O | METH_CLASS),', names[-1])
line(out, indent + 1,
'DECLARE_METHOD(t_%s, instance_, METH_O | METH_CLASS),', names[-1])
for name, methods in allMethods:
modifiers = methods[0].getModifiers()
if len(methods) == 1 and not name in superMethods:
count = len(methods[0].getParameterTypes())
if count == 0:
args = 'METH_NOARGS'
elif count == 1:
args = 'METH_O'
else:
args = 'METH_VARARGS'
elif isExtension and name == 'clone' and Modifier.isNative(modifiers):
args = 'METH_O'
else:
args = 'METH_VARARGS'
if Modifier.isStatic(modifiers):
args += ' | METH_CLASS'
line(out, indent + 1, 'DECLARE_METHOD(t_%s, %s, %s),',
names[-1], name, args)
line(out, indent + 1, '{ NULL, NULL, 0, NULL }')
line(out, indent, '};')
if instanceFields or propMethods or isExtension or clsParams:
tp_getset = 't_%s__fields_' %(names[-1])
else:
tp_getset = '0'
if iteratorMethod:
if iteratorExt:
tp_iter = 'get_extension_iterator'
else:
tp_iter = '((PyObject *(*)(t_%s *)) get_%siterator<t_%s>)' %(names[-1], clsParams and 'generic_' or '', names[-1])
tp_iternext = '0'
elif nextMethod and iterator.isAssignableFrom(cls):
tp_iter = 'PyObject_SelfIter'
returnName = typename(nextMethod.getReturnType(), cls, False)
ns, sep, n = rpartition(returnName, '::')
if nextExt:
tp_iternext = 'get_extension_next'
else:
tp_iternext = '((PyObject *(*)(java::util::t_Iterator *)) get_%siterator_next<java::util::t_Iterator,%s%st_%s>)' %(clsParams and 'generic_' or '', ns, sep, n)
elif nextElementMethod and enumeration.isAssignableFrom(cls):
tp_iter = 'PyObject_SelfIter'
returnName = typename(nextElementMethod.getReturnType(), cls, False)
ns, sep, n = rpartition(returnName, '::')
if nextElementExt:
tp_iternext = 'get_extension_nextElement'
else:
tp_iternext = '((PyObject *(*)(java::util::t_Enumeration *)) get_%senumeration_next<java::util::t_Enumeration,%s%st_%s>)' %(clsParams and 'generic_' or '', ns, sep, n)
elif nextMethod:
tp_iter = 'PyObject_SelfIter'
returnName = typename(nextMethod.getReturnType(), cls, False)
ns, sep, n = rpartition(returnName, '::')
if nextExt:
tp_iternext = 'get_extension_next'
else:
tp_iternext = '((PyObject *(*)(t_%s *)) get_%snext<t_%s,%s%st_%s,%s>)' %(names[-1], clsParams and 'generic_' or '', names[-1], ns, sep, n, returnName)
else:
tp_iter = '0'
tp_iternext = '0'
if mappingMethod:
method, cardinality = mappingMethod
if cardinality > 1:
getName = 't_%s_%s_map_' %(names[-1], method.getName())
line(out, indent, 'static PyObject *%s(t_%s *self, PyObject *key);',
getName, names[-1])
else:
getName = 't_%s_%s' %(names[-1], method.getName())
line(out)
line(out, indent, 'static PyMappingMethods t_%s_as_mapping = {',
names[-1])
line(out, indent + 1, '0,')
line(out, indent + 1, '(binaryfunc) %s,', getName)
line(out, indent + 1, '0,')
line(out, indent, '};')
tp_as_mapping = '&t_%s_as_mapping' %(names[-1])
else:
tp_as_mapping = '0'
if sequenceLenMethod or sequenceGetMethod:
if sequenceLenMethod:
method, cardinality = sequenceLenMethod
lenName = 't_%s_%s_seq_' %(names[-1], method.getName())
line(out, indent, 'static int %s(t_%s *self);', lenName, names[-1])
else:
lenName = '0'
if sequenceGetMethod:
method, cardinality = sequenceGetMethod
getName = 't_%s_%s_seq_' %(names[-1], method.getName())
line(out, indent, 'static PyObject *%s(t_%s *self, int n);',
getName, names[-1])
else:
getName = '0'
line(out)
line(out, indent, 'static PySequenceMethods t_%s_as_sequence = {',
names[-1])
if python_ver < '2.5.0':
line(out, indent + 1, '(inquiry) %s,', lenName)
line(out, indent + 1, '0,')
line(out, indent + 1, '0,')
line(out, indent + 1, '(intargfunc) %s', getName)
line(out, indent, '};')
else:
line(out, indent + 1, '(lenfunc) %s,', lenName)
line(out, indent + 1, '0,')
line(out, indent + 1, '0,')
line(out, indent + 1, '(ssizeargfunc) %s', getName)
line(out, indent, '};')
tp_as_sequence = '&t_%s_as_sequence' %(names[-1])
else:
tp_as_sequence = '0'
if len(superNames) > 1:
base = '::'.join(('::'.join(cppnames(superNames[:-1])), superNames[-1]))
else:
base = superNames[-1]
line(out)
line(out, indent, 'DECLARE_TYPE(%s, t_%s, %s, %s, %s, %s, %s, %s, %s, %s);',
names[-1], names[-1], base, cppname(names[-1]), constructorName,
tp_iter, tp_iternext, tp_getset, tp_as_mapping, tp_as_sequence)
if clsParams:
clsArgs = []
for clsParam in clsParams:
clsArgs.append("PyTypeObject *%s" %(clsParam.getName()))
line(out, indent,
"PyObject *t_%s::wrap_Object(const %s& object, %s)",
cppname(names[-1]), names[-1], ', '.join(clsArgs))
line(out, indent, "{")
line(out, indent + 1, "PyObject *obj = t_%s::wrap_Object(object);",
names[-1])
line(out, indent + 1, "if (obj != Py_None)")
line(out, indent + 1, "{")
line(out, indent + 2, "t_%s *self = (t_%s *) obj;",
names[-1], names[-1])
i = 0;
for clsParam in clsParams:
line(out, indent + 2, "self->parameters[%d] = %s;",
i, clsParam.getName())
line(out, indent + 1, "}")
line(out, indent + 1, "return obj;");
line(out, indent, "}")
line(out)
line(out, indent, 'void t_%s::install(PyObject *module)', names[-1])
line(out, indent, '{')
line(out, indent + 1, 'installType(&%s$$Type, module, "%s", %d);',
names[-1], rename or names[-1], isExtension and 1 or 0)
for inner in cls.getDeclaredClasses():
if inner in typeset:
if Modifier.isStatic(inner.getModifiers()):
innerName = inner.getName().split('.')[-1]
line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "%s", make_descriptor(&%s$$Type));',
names[-1], innerName[len(names[-1])+1:], innerName)
line(out, indent, '}')
line(out)
line(out, indent, 'void t_%s::initialize(PyObject *module)', names[-1])
line(out, indent, '{')
line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "class_", make_descriptor(%s::initializeClass, %s));',
names[-1], cppname(names[-1]), generics and 1 or 0)
line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "wrapfn_", make_descriptor(t_%s::wrap_jobject));',
names[-1], names[-1])
if isExtension:
line(out, indent + 1, 'jclass cls = %s::initializeClass();',
cppname(names[-1]))
elif fields:
line(out, indent + 1, '%s::initializeClass();', cppname(names[-1]))
if isExtension:
count = 0
line(out, indent + 1, 'JNINativeMethod methods[] = {')
for name, methods in extMethods:
for method in methods:
line(out, indent + 2, '{ "%s", "%s", (void *) t_%s_%s%d },',
name, signature(method), names[-1], name, count)
count += 1
line(out, indent + 1, '};')
line(out, indent + 1, 'env->registerNatives(cls, methods, %d);',
count)
for field in fields:
fieldType = field.getType()
fieldName = field.getName()
value = '%s::%s' %(cppname(names[-1]), cppname(fieldName))
value = fieldValue(cls, value, fieldType)
line(out, indent + 1, 'PyDict_SetItemString(%s$$Type.tp_dict, "%s", make_descriptor(%s));',
names[-1], fieldName, value)
line(out, indent, '}')
line(out)
line(out, indent, 'static PyObject *t_%s_cast_(PyTypeObject *type, PyObject *arg)', names[-1])
line(out, indent, '{')
line(out, indent + 1, 'if (!(arg = castCheck(arg, %s::initializeClass, 1)))', cppname(names[-1]))
line(out, indent + 2, 'return NULL;')
line(out, indent + 1, 'return t_%s::wrap_Object(%s(((t_%s *) arg)->object.this$));', names[-1], cppname(names[-1]), names[-1])
line(out, indent, '}')
line(out, indent, 'static PyObject *t_%s_instance_(PyTypeObject *type, PyObject *arg)', names[-1])
line(out, indent, '{')
line(out, indent + 1, 'if (!castCheck(arg, %s::initializeClass, 0))', cppname(names[-1]))
line(out, indent + 2, 'Py_RETURN_FALSE;')
line(out, indent + 1, 'Py_RETURN_TRUE;')
line(out, indent, '}')
if constructors:
line(out)
line(out, indent, 'static int t_%s_init_(t_%s *self, PyObject *args, PyObject *kwds)', names[-1], names[-1])
line(out, indent, '{')
if len(constructors) > 1:
currLen = -1
line(out, indent + 1, 'switch (PyTuple_GET_SIZE(args)) {')
withErr = False
for constructor in constructors:
params = constructor.getParameterTypes()
if len(params) != currLen:
if currLen >= 0:
withErr = True
line(out, indent + 2, 'goto err;')
currLen = len(params)
line(out, indent + 1, '%scase %d:', HALF_INDENT, currLen)
construct(out, indent + 2, cls, True, constructor, names,
generics)
line(out, indent + 1, '%sdefault:', HALF_INDENT)
if withErr:
line(out, indent + 1, '%serr:', HALF_INDENT)
line(out, indent + 2, 'PyErr_SetArgsError((PyObject *) self, "__init__", args);')
line(out, indent + 2, 'return -1;')
line(out, indent + 1, '}')
else:
construct(out, indent + 1, cls, False, constructors[0], names,
generics)
if constructors[0].getParameterTypes():
line(out, indent + 1, 'else')
line(out, indent + 1, '{')
line(out, indent + 2, 'PyErr_SetArgsError((PyObject *) self, "__init__", args);')
line(out, indent + 2, 'return -1;')
line(out, indent + 1, '}')
if isExtension:
line(out)
line(out, indent + 1, 'Py_INCREF((PyObject *) self);')
line(out, indent + 1, 'self->object.pythonExtension((jlong) (Py_intptr_t) (void *) self);')
line(out)
line(out, indent + 1, 'return 0;')
line(out, indent , '}')
for name, methods in allMethods:
line(out)
modifiers = methods[0].getModifiers()
if isExtension and name == 'clone' and Modifier.isNative(modifiers):
declargs, args, cardinality = ', PyObject *arg', ', arg', 1
else:
declargs, args, cardinality = methodargs(methods, superMethods)
static = Modifier.isStatic(modifiers)
if static:
line(out, indent, 'static PyObject *t_%s_%s(PyTypeObject *type%s)',
names[-1], name, declargs)
else:
line(out, indent, 'static PyObject *t_%s_%s(t_%s *self%s)',
names[-1], name, names[-1], declargs)
line(out, indent, '{')
if len(methods) > 1:
currLen = -1
line(out, indent + 1, 'switch (PyTuple_GET_SIZE(args)) {')
for method in methods:
params = method.getParameterTypes()
if len(params) != currLen:
if currLen >= 0:
line(out, indent + 2, 'break;')
currLen = len(params)
line(out, indent + 1, '%scase %d:', HALF_INDENT, currLen)
call(out, indent + 2, cls, True, method, names, cardinality,
isExtension, generics)
line(out, indent + 1, '}')
else:
call(out, indent + 1, cls, False, methods[0], names, cardinality,
isExtension, generics)
if args:
line(out)
if name in superMethods:
if static:
line(out, indent + 1, 'return callSuper(type, "%s"%s, %d);',
name, args, cardinality)
else:
line(out, indent + 1, 'return callSuper(&%s$$Type, (PyObject *) self, "%s"%s, %d);',
names[-1], name, args, cardinality)
else:
line(out, indent + 1, 'PyErr_SetArgsError(%s, "%s"%s);',
static and 'type' or '(PyObject *) self', name, args)
line(out, indent + 1, 'return NULL;')
line(out, indent, '}')
if isExtension:
count = 0
for name, methods in extMethods:
for method in methods:
line(out)
line(out, indent,
'static %s JNICALL t_%s_%s%d(JNIEnv *jenv, jobject jobj%s)',
jniname(method.getReturnType()), names[-1], name, count,
jniargs(method.getParameterTypes()))
count += 1
line(out, indent, '{')
extension(env, out, indent + 1, cls, names, name, count, method,
generics)
line(out, indent, '}')
line(out)
line(out, indent, 'static PyObject *t_%s_get__self(t_%s *self, void *data)',
names[-1], names[-1])
line(out, indent, '{')
indent += 1
line(out, indent, 'jlong ptr;')
line(out, indent, 'OBJ_CALL(ptr = self->object.pythonExtension());')
line(out, indent, 'PyObject *obj = (PyObject *) (Py_intptr_t) ptr;')
line(out)
line(out, indent, 'if (obj != NULL)')
line(out, indent, '{')
line(out, indent + 1, 'Py_INCREF(obj);')
line(out, indent + 1, 'return obj;')
line(out, indent, '}')
line(out, indent, 'else')
line(out, indent + 1, 'Py_RETURN_NONE;')
indent -= 1
line(out, indent, '}')
if clsParams:
line(out, indent, 'static PyObject *t_%s_get__parameters_(t_%s *self, void *data)', names[-1], names[-1])
line(out, indent, '{')
line(out, indent + 1, 'return typeParameters(self->parameters, sizeof(self->parameters));')
line(out, indent, '}')
if instanceFields:
for field in instanceFields:
fieldName = field.getName()
if fieldName not in properties:
line(out)
fieldType = field.getType()
typeName = typename(fieldType, cls, False)
line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data)',
names[-1], fieldName, names[-1])
line(out, indent, '{')
line(out, indent + 1, '%s value%s;', typeName,
not fieldType.isPrimitive() and '((jobject) NULL)' or '')
line(out, indent + 1, 'OBJ_CALL(value = self->object._get_%s());',
fieldName)
line(out, indent + 1, returnValue(cls, fieldType, 'value'))
line(out, indent, '}')
if not Modifier.isFinal(field.getModifiers()):
line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data)',
names[-1], fieldName, names[-1])
line(out, indent, '{')
line(out, indent + 1, '%s value%s;', typeName,
not fieldType.isPrimitive() and '((jobject) NULL)' or '')
sig, check, x = parseArgs([fieldType], cls, False)
line(out, indent + 1, 'if (!parseArg(arg, "%s"%s, &value))',
sig, check)
line(out, indent + 1, '{')
line(out, indent + 2, 'INT_CALL(self->object._set_%s(value));',
fieldName)
line(out, indent + 2, 'return 0;')
line(out, indent + 1, '}')
line(out, indent + 1, 'PyErr_SetArgsError((PyObject *) self, "%s", arg);',
fieldName)
line(out, indent + 1, 'return -1;')
line(out, indent, '}')
if propMethods:
for fieldName, methods in propMethods:
line(out)
getter = None
setters = []
sort(methods, key=lambda x: x.getName())
for method in methods:
methodName = method.getName()
if not getter and (methodName.startswith('get') or
methodName.startswith('is')):
getter = method
elif methodName.startswith('set'):
setters.append(method)
if getter:
methodName = getter.getName()
returnType = getter.getReturnType()
typeName = typename(returnType, cls, False)
line(out, indent, 'static PyObject *t_%s_get__%s(t_%s *self, void *data)',
names[-1], fieldName, names[-1])
line(out, indent, '{')
line(out, indent + 1, '%s value%s;', typeName,
not returnType.isPrimitive() and '((jobject) NULL)' or '')
line(out, indent + 1, 'OBJ_CALL(value = self->object.%s());',
methodName)
line(out, indent + 1, returnValue(cls, returnType, 'value'))
line(out, indent, '}')
if setters:
line(out, indent, 'static int t_%s_set__%s(t_%s *self, PyObject *arg, void *data)',
names[-1], fieldName, names[-1])
line(out, indent, '{')
methodName = setters[0].getName()
for method in setters:
argType = method.getParameterTypes()[0]
typeName = typename(argType, cls, False)
line(out, indent + 1, '{')
line(out, indent + 2, '%s value%s;', typeName,
not argType.isPrimitive() and '((jobject) NULL)' or '')
sig, check, x = parseArgs([argType], cls, False)
line(out, indent + 2, 'if (!parseArg(arg, "%s"%s, &value))',
sig, check)
line(out, indent + 2, '{')
line(out, indent + 3, 'INT_CALL(self->object.%s(value));',
methodName)
line(out, indent + 3, 'return 0;')
line(out, indent + 2, '}')
line(out, indent + 1, '}')
line(out, indent + 1, 'PyErr_SetArgsError((PyObject *) self, "%s", arg);',
fieldName)
line(out, indent + 1, 'return -1;')
line(out, indent, '}')
if mappingMethod:
method, cardinality = mappingMethod
if cardinality > 1:
methodName = method.getName()
getName = 't_%s_%s_map_' %(names[-1], methodName)
line(out)
line(out, indent, 'static PyObject *%s(t_%s *self, PyObject *arg)',
getName, names[-1])
line(out, indent, '{')
call(out, indent + 1, cls, False, method, names, 1, isExtension,
generics)
line(out)
line(out, indent + 1, 'PyErr_SetArgsError((PyObject *) self, "%s", arg);',
methodName)
line(out, indent + 1, 'return NULL;')
line(out, indent, '}')
if sequenceLenMethod:
method, cardinality = sequenceLenMethod
methodName = method.getName()
lenName = 't_%s_%s_seq_' %(names[-1], methodName)
line(out)
line(out, indent, 'static int %s(t_%s *self)', lenName, names[-1])
line(out, indent, '{')
line(out, indent + 1, '%s len;',
typename(method.getReturnType(), cls, False))
line(out, indent + 1, 'INT_CALL(len = self->object.%s());', methodName)
line(out, indent + 1, 'return (int) len;')
line(out, indent, '}')
if sequenceGetMethod:
method, cardinality = sequenceGetMethod
methodName = method.getName()
returnType = method.getReturnType()
getName = 't_%s_%s_seq_' %(names[-1], methodName)
line(out)
line(out, indent, 'static PyObject *%s(t_%s *self, int n)', getName, names[-1])
line(out, indent, '{')
line(out, indent + 1, '%s result%s;',
typename(returnType, cls, False),
not returnType.isPrimitive() and '((jobject) NULL)' or '')
line(out, indent + 1, 'OBJ_CALL(result = self->object.%s((%s) n));',
methodName, typename(method.getParameterTypes()[0], cls, False))
line(out, indent + 1, returnValue(cls, returnType, 'result'))
line(out, indent, '}')
while indent:
indent -= 1
line(out, indent, '}')
def package(out, allInOne, cppdir, namespace, names):
if not allInOne:
out = file(os.path.join(os.path.join(cppdir, *names),
'__init__.cpp'), 'w')
if allInOne and not names or not allInOne:
line(out, 0, '#include <jni.h>')
line(out, 0, '#include <Python.h>')
line(out, 0, '#include "JCCEnv.h"')
line(out, 0, '#include "functions.h"')
if not names:
line(out)
line(out, 0, 'PyObject *initVM(PyObject *module, PyObject *args, PyObject *kwds);')
packages = []
types = []
namespaces = namespace.items()
sort(namespaces, key=lambda x: x[0])
for name, entries in namespaces:
if entries is True:
if names:
line(out, 0, '#include "%s/%s.h"', '/'.join(names), name)
else:
line(out, 0, '#include "%s.h"', name)
types.append(name)
else:
packages.append((name, entries))
indent = 0
if names:
line(out)
for name in names:
line(out, indent, 'namespace %s {', cppname(name))
indent += 1
line(out);
for name, entries in packages:
line(out, indent, 'namespace %s {', cppname(name))
line(out, indent + 1, 'void __install__(PyObject *module);')
line(out, indent + 1, 'void __initialize__(PyObject *module);')
line(out, indent, '}')
line(out)
line(out, indent, 'void __install__(PyObject *module)')
line(out, indent, '{')
for name in types:
line(out, indent + 1, 't_%s::install(module);', name)
for name, entries in packages:
line(out, indent + 1, '%s::__install__(module);', cppname(name))
line(out, indent, '}')
line(out)
if not names:
line(out, indent, 'PyObject *__initialize__(PyObject *module, PyObject *args, PyObject *kwds)')
line(out, indent, '{')
line(out, indent + 1, 'PyObject *env = initVM(module, args, kwds);')
line(out)
line(out, indent + 1, 'if (env == NULL)')
line(out, indent + 2, 'return NULL;')
line(out)
line(out, indent + 1, 'try {');
indent += 1
else:
line(out, indent, 'void __initialize__(PyObject *module)')
line(out, indent, '{')
for name in types:
line(out, indent + 1, 't_%s::initialize(module);', name)
for name, entries in packages:
line(out, indent + 1, '%s::__initialize__(module);', cppname(name))
if not names:
line(out, indent + 1, 'return env;')
indent -= 1
line(out, indent + 1, '} catch (JCCEnv::exception e) {')
line(out, indent + 2, 'PyErr_SetJavaError(e.throwable);')
line(out, indent + 2, 'return NULL;')
line(out, indent + 1, '}')
line(out, indent, '}')
while indent:
indent -= 1
line(out, indent, '}')
if not allInOne:
out.close()
else:
line(out)
for name, entries in packages:
package(out, allInOne, cppdir, entries, names + (name,))
def module(out, allInOne, classes, cppdir, moduleName, shared, generics):
extname = '_%s' %(moduleName)
line(out, 0, '#include <Python.h>')
line(out, 0, '#include "macros.h"')
line(out, 0, '#include "jccfuncs.h"')
if allInOne:
out_init = file(os.path.join(cppdir, '__init__.cpp'), 'w')
namespaces = {}
for cls in classes:
namespace = namespaces
classNames = cls.getName().split('.')
for className in classNames[:-1]:
namespace = namespace.setdefault(className, {})
namespace[classNames[-1]] = True
if allInOne:
package(out_init, True, cppdir, namespaces, ())
out_init.close()
else:
package(None, False, cppdir, namespaces, ())
line(out)
line(out, 0, 'PyObject *initJCC(PyObject *module);')
line(out, 0, 'void __install__(PyObject *module);')
line(out, 0, 'extern PyTypeObject JObject$$Type, ConstVariableDescriptor$$Type, FinalizerClass$$Type, FinalizerProxy$$Type;')
line(out, 0, 'extern void _install_jarray(PyObject *);')
line(out)
line(out, 0, 'extern "C" {')
line(out)
line(out, 1, 'void init%s(void)', extname)
line(out, 1, '{')
line(out, 2, 'PyObject *module = Py_InitModule3("%s", jcc_funcs, "");',
extname);
line(out)
line(out, 2, 'initJCC(module);')
line(out)
line(out, 2, 'INSTALL_TYPE(JObject, module);')
line(out, 2, 'INSTALL_TYPE(ConstVariableDescriptor, module);')
line(out, 2, 'INSTALL_TYPE(FinalizerClass, module);')
line(out, 2, 'INSTALL_TYPE(FinalizerProxy, module);')
line(out, 2, '_install_jarray(module);')
line(out, 2, '__install__(module);')
line(out, 1, '}')
line(out, 0, '}')
def compile(env, jccPath, output, moduleName, install, dist, debug, jars,
version, prefix, root, install_dir, home_dir, use_distutils,
shared, compiler, modules, wininst, arch, generics):
try:
if use_distutils:
raise ImportError
from setuptools import setup, Extension
with_setuptools = True
if shared and not SHARED:
raise NotImplementedError, "JCC was not built with --shared mode support, see JCC's INSTALL file for more information"
except ImportError:
if python_ver < '2.4':
raise ImportError, 'setuptools is required when using Python 2.3'
if shared:
raise ImportError, 'setuptools is required when using --shared'
from distutils.core import setup, Extension
with_setuptools = False
extname = '_%s' %(moduleName)
modulePath = os.path.join(output, moduleName)
if not os.path.isdir(modulePath):
os.makedirs(modulePath)
out = file(os.path.join(modulePath, '__init__.py'), 'w')
line(out)
if shared:
line(out, 0, "import os, sys")
line(out)
line(out, 0, "if sys.platform == 'win32':")
line(out, 1, "import jcc, %s", extname)
line(out, 0, "else:")
line(out, 1, "import %s", extname)
else:
line(out, 0, 'import os, %s', extname)
line(out)
line(out, 0, '__dir__ = os.path.abspath(os.path.dirname(__file__))')
package_data = []
for jar in jars:
shutil.copy2(jar, modulePath)
package_data.append(os.path.basename(jar))
packages = [moduleName]
if modules:
for module in modules:
if os.path.isdir(module):
def copytree(src, dst, is_package):
if is_package:
packages.append('.'.join((moduleName, src.replace(os.path.sep, '.'))))
if not os.path.exists(dst):
os.mkdir(dst)
for name in os.listdir(src):
if name.startswith('.'):
continue
_src = os.path.join(src, name)
if os.path.islink(_src):
continue
_dst = os.path.join(dst, name)
if os.path.isdir(_src):
copytree(_src, _dst, os.path.exists(os.path.join(_src, '__init__.py')))
elif not is_package or name.endswith('.py'):
shutil.copy2(_src, _dst)
dst = modulePath
if os.path.exists(os.path.join(module, '__init__.py')):
dst = os.path.join(modulePath, os.path.basename(module))
copytree(module, dst, True)
else:
copytree(module, dst, False)
else:
shutil.copy2(module.split('.')[0] + '.py', modulePath)
line(out)
line(out, 0, 'class JavaError(Exception):')
line(out, 1, 'def getJavaException(self):')
line(out, 2, 'return self.args[0]')
line(out, 1, 'def __str__(self):')
line(out, 2, 'writer = %s.StringWriter()', extname)
line(out, 2, 'self.getJavaException().printStackTrace(%s.PrintWriter(writer))', extname)
line(out, 2, 'return "\\n".join((super(JavaError, self).__str__(), " Java stacktrace:", str(writer)))')
line(out)
line(out, 0, 'class InvalidArgsError(Exception):')
line(out, 1, 'pass')
line(out)
line(out, 0, '%s._set_exception_types(JavaError, InvalidArgsError)',
extname)
if version:
line(out)
line(out, 0, 'VERSION = "%s"', version)
line(out, 0, 'CLASSPATH = [%s]' %(', '.join(['os.path.join(__dir__, "%s")' %(os.path.basename(jar)) for jar in jars])))
line(out, 0, 'CLASSPATH = os.pathsep.join(CLASSPATH)')
line(out, 0, '%s.CLASSPATH = CLASSPATH', extname)
line(out, 0, '%s._set_function_self(%s.initVM, %s)',
extname, extname, extname)
line(out)
line(out, 0, 'from %s import *', extname)
out.close()
includes = [os.path.join(output, extname),
os.path.join(jccPath, 'sources')]
sources = ['JObject.cpp', 'JArray.cpp', 'functions.cpp', 'types.cpp']
if not shared:
sources.append('jcc.cpp')
sources.append('JCCEnv.cpp')
for source in sources:
shutil.copy2(os.path.join(jccPath, 'sources', source),
os.path.join(output, extname))
sources = []
for path, dirs, names in os.walk(os.path.join(output, extname)):
for name in names:
if name.endswith('.cpp'):
sources.append(os.path.join(path, name))
script_args = ['build_ext']
includes[0:0] = INCLUDES
compile_args = CFLAGS
link_args = LFLAGS
defines=['PYTHON']
if compiler:
script_args.append('--compiler=%s' %(compiler))
if shared:
defines.append('_jcc_shared')
script_args.append('--define=%s' %(','.join(defines)))
if debug:
script_args.append('--debug')
compile_args += DEBUG_CFLAGS
elif sys.platform == 'win32':
pass
elif sys.platform == 'sunos5':
link_args.append('-Wl,-s')
else:
link_args.append('-Wl,-S')
if install:
script_args.append('install')
if prefix:
script_args.append('--prefix=%s' % prefix)
if root:
script_args.append('--root=%s' % root)
if install_dir:
script_args.append('--install-lib=%s' % install_dir)
if home_dir:
script_args.append('--home=%s' % home_dir)
if dist:
if wininst:
script_args.append('bdist_wininst')
elif with_setuptools:
script_args.append('bdist_egg')
else:
script_args.append('bdist')
args = {
'extra_compile_args': compile_args,
'extra_link_args': link_args,
'include_dirs': includes,
'sources': sources
}
if generics:
args['define_macros'] = [('_java_generics', None)]
if shared:
shlibdir = os.path.dirname(os.path.dirname(_jcc.__file__))
if sys.platform == 'darwin': # distutils no good with -R
machine = platform.machine()
if machine.startswith('iPod') or machine.startswith('iPhone'):
args['extra_link_args'] += ['-L' + shlibdir]
else:
args['extra_link_args'] += ['-Wl,-rpath', shlibdir]
args['library_dirs'] = [shlibdir]
args['libraries'] = ['jcc']
elif sys.platform == 'linux2': # distutils no good with -R
args['extra_link_args'] += ['-Wl,-rpath', shlibdir]
args['library_dirs'] = [shlibdir]
args['libraries'] = ['jcc']
elif sys.platform == 'win32':
jcclib = 'jcc%s.lib' %(debug and '_d' or '')
args['extra_link_args'] += [os.path.join(shlibdir, 'jcc', jcclib)]
else:
raise NotImplementedError, "shared mode on %s" %(sys.platform)
if arch and sys.platform == 'darwin':
from distutils import sysconfig
config_vars = sysconfig.get_config_vars()
cflags = config_vars['CFLAGS'].split(' ')
count = len(cflags)
i = 0
while i < count - 1:
if cflags[i] == '-arch' and cflags[i + 1] not in arch:
del cflags[i:i+2]
count -= 2
else:
i += 1
config_vars['CFLAGS'] = ' '.join(cflags)
extensions = [Extension('.'.join([moduleName, extname]), **args)]
args = {
'name': moduleName,
'packages': packages,
'package_dir': {moduleName: modulePath},
'package_data': {moduleName: package_data},
'version': version,
'ext_modules': extensions,
'script_args': script_args
}
if with_setuptools:
args['zip_safe'] = False
setup(**args)