Repository URL to install this package:
|
Version:
3.5 ▾
|
JCC
/
python.py
|
|---|
#
# 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
from . import _jcc3
from .cpp import PRIMITIVES, INDENT, HALF_INDENT
from .cpp import RENAME_METHOD_SUFFIX, RENAME_FIELD_SUFFIX
from .cpp import cppname, cppnames, absname, typename, findClass
from .cpp import line, signature, find_method
from .cpp import Modifier, Class, Method
from .cpp import getActualTypeArguments, getTypeParameters
from .config import INCLUDES, CFLAGS, DEBUG_CFLAGS, LFLAGS, IMPLIB_LFLAGS, \
SHARED, VERSION as JCC_VER
try:
from .cpp import ParameterizedType, TypeVariable
except ImportError:
pass
RESULTS = { 'boolean': 'Py_RETURN_BOOL(%s);',
'byte': 'return PyLong_FromLong((long) %s);',
'char': 'return c2p(%s);',
'double': 'return PyFloat_FromDouble((double) %s);',
'float': 'return PyFloat_FromDouble((double) %s);',
'int': 'return PyLong_FromLong((long) %s);',
'long': 'return PyLong_FromLongLong((PY_LONG_LONG) %s);',
'short': 'return PyLong_FromLong((long) %s);',
'java.lang.String': 'return j2p(%s);' }
CALLARGS = { 'boolean': ('O', '(%s ? Py_True : Py_False)', False),
'byte': ('O', 'PyLong_FromLong(%s)', True),
'char': ('O', 'c2p(%s);', 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) }
BOXED = { 'java.lang.Boolean': (True, True),
'java.lang.Byte': (True, True),
'java.lang.Character': (True, True),
'java.lang.CharSequence': (True, False),
'java.lang.Double': (True, True),
'java.lang.Float': (True, True),
'java.lang.Integer': (True, True),
'java.lang.Long': (True, True),
'java.lang.Number': (True, False),
'java.lang.Short': (True, True),
'java.lang.String': (True, True) }
def is_boxed(clsName):
return BOXED.get(clsName, (False, False))[0]
def is_unboxed(clsName):
return BOXED.get(clsName, (False, False))[1]
def parseArgs(params, current, generics, genericParams=None):
def signature(cls, genericPT=None):
if generics and TypeVariable.instance_(genericPT):
if cls.getName() == 'java.lang.Object':
gd = TypeVariable.cast_(genericPT).getGenericDeclaration()
if gd == current:
for clsParam in getTypeParameters(gd):
if genericPT == clsParam:
return 'O'
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 is_boxed(clsName):
return array + 'O'
if generics and getTypeParameters(cls):
return array + 'K'
else:
return array + 'k'
def checkarg(cls, genericPT=None):
if generics and TypeVariable.instance_(genericPT):
if cls.getName() == 'java.lang.Object':
gd = TypeVariable.cast_(genericPT).getGenericDeclaration()
if gd == current:
i = 0
for clsParam in getTypeParameters(gd):
if genericPT == clsParam:
return ', self->parameters[%d]' %(i)
i += 1
while cls.isArray():
cls = cls.getComponentType()
clsName = cls.getName()
if (cls.isPrimitive() or
clsName in ('java.lang.String', 'java.lang.Object')):
return ''
if is_boxed(clsName):
clsNames = clsName.split('.')
return ', %s::PY_TYPE(%s)' %(absname(cppnames(clsNames[:-1])), cppname(clsNames[-1]))
return ', %s::initializeClass' %(typename(cls, current, False))
def callarg(cls, i):
if generics:
while cls.isArray():
cls = cls.getComponentType()
if getTypeParameters(cls):
ns, sep, n = typename(cls, current, False).rpartition('::')
return ', &a%d, &p%d, %s%st_%s::parameters_' %(i, i, ns, sep, n)
return ', &a%d' %(i)
if genericParams:
sig = ''.join([signature(param, genericParam)
for param, genericParam in zip(params, genericParams)])
chk = ''.join([checkarg(param, genericParam)
for param, genericParam in zip(params, genericParams)])
else:
sig = ''.join([signature(param) for param in params])
chk = ''.join([checkarg(param) for param in params])
return (sig, chk,
''.join([callarg(params[i], i) for i in range(len(params))]))
def declareVars(out, indent, params, current, generics, typeParams):
for i in range(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 getTypeParameters(param):
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 range(count)]))
line(out, indent, 'self->object = object;')
if generics:
clsParams = getTypeParameters(cls)
i = 0
for clsParam in clsParams:
if Class.instance_(clsParam):
cls = Class.cast_(clsParam)
if cls.isArray():
cls = cls.getComponentType()
if cls.isArray():
clsNames = 'java.lang.Object'.split('.')
clsArg = '%s::PY_TYPE(%s)' %(absname(cppnames(clsNames[:-1])), cppname(clsNames[-1]))
elif cls.isPrimitive():
clsArg = 'PY_TYPE(JArray%s)' %(cls.getName().capitalize())
else:
clsArg = 'PY_TYPE(JArrayObject)'
else:
clsNames = cls.getName().split('.')
clsArg = '%s::PY_TYPE(%s)' %(absname(cppnames(clsNames[:-1])), cppname(clsNames[-1]))
line(out, indent, 'self->parameters[%d] = %s;', i, clsArg)
i += 1
if inCase:
line(out, indent, 'break;')
if count:
indent -= 1
line(out, indent, '}')
if inCase:
indent -= 1
line(out, indent, '}')
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 = typename(fieldType, cls, False).rpartition('::')
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 = typename(fieldType, cls, False).rpartition('::')
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 = typename(returnType, cls, False).rpartition('::')
return 'return JArray<jobject>(%s.this$).wrap(%s%st_%s::wrap_jobject);' %(value, ns, sep, n)
ns, sep, n = typename(returnType, cls, False).rpartition('::')
if genericRT is not None:
if ParameterizedType.instance_(genericRT):
genericRT = ParameterizedType.cast_(genericRT)
clsArgs = []
for clsArg in getActualTypeArguments(genericRT):
if Class.instance_(clsArg):
clsArg = Class.cast_(clsArg)
if clsArg.isArray():
clsArg = Class.forName('java.lang.Object')
clsNames = clsArg.getName().split('.')
clsArg = '%s::PY_TYPE(%s)' %(absname(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 getTypeParameters(gd):
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 getTypeParameters(gd):
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 getTypeParameters(gd):
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()
genericParams = method.getGenericParameterTypes()
typeParams = set()
else:
genericRT = None
genericParams = 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, genericParams))
line(out, indent, '{')
indent += 1
name = cppname(name)
if Modifier.isStatic(modifiers):
line(out, indent, 'OBJ_CALL(%s%s::%s(%s));',
result, absname(cppnames(names)), name,
', '.join(['a%d' %(i) for i in range(count)]))
else:
line(out, indent, 'OBJ_CALL(%sself->object.%s(%s));',
result, name, ', '.join(['a%d' %(i) for i in range(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, PY_TYPE(FinalizerProxy)) &&')
line(out, indent, ' PyObject_TypeCheck(((t_fp *) arg)->object, Py_TYPE(self)))')
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 range(count)])
if decls:
return ', ' + decls
return ''
def wrapper_typename(returnType, cls):
if returnType.isArray():
componentType = returnType.getComponentType()
componentName = typename(componentType, cls, False)
if componentType.isPrimitive():
return "t_JArrayWrapper< %s >" %(componentName)
ns, sep, n = componentName.rpartition('::')
return "t_JArrayWrapper< jobject,%s%st_%s >" %(ns, sep, n)
returnName = typename(returnType, cls, False)
ns, sep, n = returnName.rpartition('::')
return "%s%st_%s" %(ns, sep, n)
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 = typename(param, cls, False).rpartition('::')
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 = typename(param, cls, False).rpartition('::')
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, superClasses, names, superNames,
constructors, methods, protectedMethods,
methodNames, fields, instanceFields,
mapping, sequence, rename, declares, typeset, moduleName, generics,
_dll_export):
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, '%sextern PyType_Def PY_TYPE_DEF(%s);',
_dll_export, names[-1])
line(out_h, indent, '%sextern PyTypeObject *PY_TYPE(%s);',
_dll_export, names[-1])
if generics:
clsParams = getTypeParameters(cls)
else:
clsParams = None
line(out_h)
line(out_h, indent, 'class %st_%s {', _dll_export, 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]))
line(out_h, indent + 1, 'static PyObject *wrap_jobject(const jobject&);')
if clsParams:
_clsParams = ', '.join(['PyTypeObject *'] * len(clsParams))
line(out_h, indent + 1, 'static PyObject *wrap_Object(const %s&, %s);',
cppname(names[-1]), _clsParams)
line(out_h, indent + 1, 'static PyObject *wrap_jobject(const jobject&, %s);', _clsParams)
line(out_h, indent + 1, 'static void install(PyObject *module);')
line(out_h, indent + 1, 'static void initialize(PyObject *module);')
line(out_h, indent, '};')
if env.java_version >= '1.5':
iterable = findClass('java/lang/Iterable')
iterator = findClass('java/util/Iterator')
else:
iterable = iterator = None
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 clsParams:
line(out, indent,
'static PyObject *t_%s_of_(t_%s *self, PyObject *args);',
names[-1], 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 superClasses:
superMethods = set([method.getName()
for superCls in superClasses
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 superClasses and isNative):
superMethod = find_method(superClasses[0], 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 + RENAME_METHOD_SUFFIX in allMethods:
allMethods[name + RENAME_METHOD_SUFFIX].append(method)
else:
print(" Warning: renaming static method '%s' on class %s to '%s%s' since it is shadowed by non-static method of same name." %(name, '.'.join(names), name, RENAME_METHOD_SUFFIX), file=sys.stderr)
allMethods[name + RENAME_METHOD_SUFFIX] = [method]
else:
allMethods[name] = [method]
else:
if name in allMethods:
if Modifier.isStatic(allMethods[name][0].getModifiers()):
print(" Warning: renaming static method '%s' on class %s to '%s%s' since it is shadowed by non-static method of same name." %(name, '.'.join(names), name, RENAME_METHOD_SUFFIX), file=sys.stderr)
allMethods[name + RENAME_METHOD_SUFFIX] = 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'):
if method.getReturnType().getName() != 'void':
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'):
if method.getReturnType().getName() != 'void':
propMethods.setdefault(name[2].lower() + name[3:],
[]).append(method)
properties = set([name for name in propMethods.keys()
if name not in allMethods])
propMethods = [(name, propMethods[name]) for name in properties]
propMethods.sort(key=lambda x: x[0])
extMethods = list(extMethods.items())
extMethods.sort(key=lambda x: x[0])
allMethods = list(allMethods.items())
allMethods.sort(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)
methods.sort(key=lambda x: len(x.getParameterTypes()))
method = methods[0]
modifiers = method.getModifiers()
if name == 'iterator' and iteratorMethod is None:
if (iterable is not None and
not method.getParameterTypes() and
iterable.isAssignableFrom(cls) 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)
methods.sort(key=lambda x: len(x.getParameterTypes()))
method = methods[0]
modifiers = method.getModifiers()
if name == 'iterator' and iteratorMethod is None:
if (iterable is not None and
not method.getParameterTypes() and
iterable.isAssignableFrom(cls) 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])
if clsParams:
line(out, indent + 1,
'DECLARE_METHOD(t_%s, of_, METH_VARARGS),', 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 = None
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 iterable is not None and iterator.isAssignableFrom(cls):
tp_iter = 'PyObject_SelfIter'
if nextExt:
tp_iternext = 'get_extension_next'
else:
tp_iternext = '((PyObject *(*)(::java::util::t_Iterator *)) get_%siterator_next< ::java::util::t_Iterator,%s >)' %(clsParams and 'generic_' or '', wrapper_typename(nextMethod.getReturnType(), cls))
elif nextElementMethod and enumeration.isAssignableFrom(cls):
tp_iter = 'PyObject_SelfIter'
returnName = typename(nextElementMethod.getReturnType(), cls, False)
ns, sep, n = returnName.rpartition('::')
if nextElementExt:
tp_iternext = 'get_extension_nextElement'
else:
tp_iternext = '((PyObject *(*)(::java::util::t_Enumeration *)) get_%senumeration_next< ::java::util::t_Enumeration,%s >)' %(clsParams and 'generic_' or '', wrapper_typename(nextElementMethod.getReturnType(), cls))
elif nextMethod:
tp_iter = 'PyObject_SelfIter'
if nextExt:
tp_iternext = 'get_extension_next'
else:
returnType = nextMethod.getReturnType()
tp_iternext = '((PyObject *(*)(t_%s *)) get_%snext< t_%s,%s,%s >)' %(names[-1], clsParams and 'generic_' or '', names[-1], wrapper_typename(returnType, cls), typename(returnType, cls, False))
else:
tp_iter = None
tp_iternext = None
if mappingMethod:
method, cardinality = mappingMethod
if cardinality > 1:
mp_subscript = 't_%s_%s_map_' %(names[-1], method.getName())
line(out, indent, 'static PyObject *%s(t_%s *self, PyObject *key);',
mp_subscript, names[-1])
else:
mp_subscript = 't_%s_%s' %(names[-1], method.getName())
else:
mp_subscript = None
if sequenceLenMethod:
method, cardinality = sequenceLenMethod
sq_length = 't_%s_%s_seq_' %(names[-1], method.getName())
line(out, indent, 'static int %s(t_%s *self);',
sq_length, names[-1])
else:
sq_length = None
if sequenceGetMethod:
method, cardinality = sequenceGetMethod
sq_item = 't_%s_%s_seq_' %(names[-1], method.getName())
line(out, indent, 'static PyObject *%s(t_%s *self, int n);',
sq_item, names[-1])
else:
sq_item = None
line(out)
line(out, indent, 'static PyType_Slot PY_TYPE_SLOTS(%s)[] = {', names[-1])
line(out, indent + 1, '{ Py_tp_methods, t_%s__methods_ },', names[-1])
line(out, indent + 1, '{ Py_tp_init, (void *) %s },', constructorName)
if tp_getset is not None:
line(out, indent + 1, '{ Py_tp_getset, %s },', tp_getset)
if tp_iter is not None:
line(out, indent + 1, '{ Py_tp_iter, (void *) %s },', tp_iter)
line(out, indent + 1, '{ Py_tp_iternext, (void *) %s },', tp_iternext)
if mp_subscript is not None:
line(out, indent + 1, '{ Py_mp_subscript, (void *) %s },', mp_subscript)
if sq_length is not None:
line(out, indent + 1, '{ Py_sq_length, (void *) %s },', sq_length)
if sq_item is not None:
line(out, indent + 1, '{ Py_sq_item, (void *) %s },', sq_item)
line(out, indent + 1, '{ 0, NULL }')
line(out, indent, '};')
line(out)
line(out, indent, 'static PyType_Def *PY_TYPE_BASES(%s)[] = {', names[-1])
for superName in superNames:
if len(superName) > 1:
base = '::'.join((absname(cppnames(superName[:-1])), superName[-1]))
else:
base = superName[-1]
line(out, indent + 1, '&PY_TYPE_DEF(%s),', base)
line(out, indent + 1, 'NULL')
line(out, indent, '};')
line(out)
line(out, indent, 'DEFINE_TYPE(%s, t_%s, %s);',
names[-1], names[-1], cppname(names[-1]))
if clsParams:
clsArgs = []
i = 0
for clsParam in clsParams:
clsArgs.append("PyTypeObject *p%d" %(i))
i += 1
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 != NULL && 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] = p%d;",
i, i)
i += 1
line(out, indent + 1, "}")
line(out, indent + 1, "return obj;");
line(out, indent, "}")
line(out)
line(out, indent,
"PyObject *t_%s::wrap_jobject(const jobject& object, %s)",
cppname(names[-1]), ', '.join(clsArgs))
line(out, indent, "{")
line(out, indent + 1, "PyObject *obj = t_%s::wrap_jobject(object);",
names[-1])
line(out, indent + 1, "if (obj != NULL && 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] = p%d;",
i, i)
i += 1
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(&PY_TYPE(%s), &PY_TYPE_DEF(%s), module, "%s", %d);',
names[-1], 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, 'PyObject_SetAttrString((PyObject *) PY_TYPE(%s), "%s", make_descriptor(&PY_TYPE_DEF(%s)));',
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, 'PyObject_SetAttrString((PyObject *) PY_TYPE(%s), "class_", make_descriptor(%s::initializeClass, %s));',
names[-1], cppname(names[-1]), generics and 1 or 0)
if is_unboxed(cls.getName()):
wrapfn_ = "unbox%s" %(names[-1])
boxfn_ = "box%s" %(names[-1])
else:
wrapfn_ = "t_%s::wrap_jobject" %(names[-1])
boxfn_ = "boxObject"
line(out, indent + 1, 'PyObject_SetAttrString((PyObject *) PY_TYPE(%s), "wrapfn_", make_descriptor(%s));', names[-1], wrapfn_)
line(out, indent + 1, 'PyObject_SetAttrString((PyObject *) PY_TYPE(%s), "boxfn_", make_descriptor(%s));', names[-1], boxfn_)
if isExtension:
line(out, indent + 1, 'jclass cls = env->getClass(%s::initializeClass);',
cppname(names[-1]))
elif fields:
line(out, indent + 1, 'env->getClass(%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()
cppFieldName = cppname(fieldName)
if cppFieldName in methodNames:
fieldName += RENAME_FIELD_SUFFIX
cppFieldName += RENAME_FIELD_SUFFIX
value = '%s::%s' %(cppname(names[-1]), cppFieldName)
value = fieldValue(cls, value, fieldType)
line(out, indent + 1, 'PyObject_SetAttrString((PyObject *) PY_TYPE(%s), "%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 clsParams:
line(out)
line(out, indent,
'static PyObject *t_%s_of_(t_%s *self, PyObject *args)',
names[-1], names[-1])
line(out, indent, '{')
line(out, indent + 1,
'if (!parseArg(args, "T", %d, &(self->parameters)))',
len(clsParams))
line(out, indent + 2, 'Py_RETURN_SELF;');
line(out, indent + 1,
'return PyErr_SetArgsError((PyObject *) self, "of_", args);')
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(PY_TYPE(%s), (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 = []
methods.sort(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))
if generics:
line(out, indent + 1, returnValue(cls, returnType, 'result',
method.getGenericReturnType()))
else:
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, use_full_names):
if not allInOne:
out = open(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);')
if use_full_names:
line(out, 0, 'PyObject *getJavaModule(PyObject *module, const char *parent, const char *name);')
packages = []
types = []
namespaces = list(namespace.items())
namespaces.sort(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, '{')
if use_full_names and names:
parent_name = '.'.join(names[:-1])
line(out, indent + 1, 'module = getJavaModule(module, "%s", "%s");',
parent_name, names[-1])
line(out)
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, '{')
if use_full_names and names:
line(out, indent + 1, 'module = getJavaModule(module, "%s", "%s");',
parent_name, names[-1])
line(out)
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 (int e) {')
line(out, indent + 2, 'switch(e) {')
line(out, indent + 2, ' case _EXC_JAVA:')
line(out, indent + 3, 'return PyErr_SetJavaError();')
line(out, indent + 2, ' default:')
line(out, indent + 3, 'throw;')
line(out, indent + 2, '}')
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,), use_full_names)
def module(out, allInOne, classes, imports, cppdir, moduleName,
shared, generics, use_full_names):
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 = open(os.path.join(cppdir, '__init__.cpp'), 'w')
namespaces = {}
for cls in classes:
for importset in imports.values():
if cls in importset:
break
else:
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, (), use_full_names)
out_init.close()
else:
package(None, False, cppdir, namespaces, (), use_full_names)
line(out)
line(out, 0, 'PyObject *initJCC(PyObject *module);')
line(out, 0, 'void __install__(PyObject *module);')
line(out, 0, 'extern PyTypeObject *PY_TYPE(JObject), *PY_TYPE(ConstVariableDescriptor), *PY_TYPE(FinalizerClass), *PY_TYPE(FinalizerProxy);')
line(out, 0, 'extern PyType_Def PY_TYPE_DEF(JObject);')
line(out, 0, 'extern void _install_jarray(PyObject *);')
line(out)
line(out, 0, 'extern "C" {')
line(out, 1, 'static struct PyModuleDef %s_def = {', extname)
line(out, 2, 'PyModuleDef_HEAD_INIT,')
line(out, 2, '"%s",', extname);
line(out, 2, '"%s module",', extname);
line(out, 2, '0,')
line(out, 2, 'jcc_funcs,');
line(out, 1, '};')
line(out)
line(out, 1, 'PyObject *PyInit_%s(void)', extname)
line(out, 1, '{')
line(out, 2, 'PyObject *module = PyModule_Create(&%s_def);', extname);
line(out)
line(out, 2, 'initJCC(module);')
line(out)
line(out, 2, 'INSTALL_STATIC_TYPE(JObject, module);')
line(out, 2, 'PY_TYPE_DEF(JObject).type = PY_TYPE(JObject);')
line(out, 2, 'INSTALL_STATIC_TYPE(ConstVariableDescriptor, module);')
line(out, 2, 'INSTALL_STATIC_TYPE(FinalizerClass, module);')
line(out, 2, 'INSTALL_STATIC_TYPE(FinalizerProxy, module);')
line(out, 2, '__install__(module);')
line(out, 2, '_install_jarray(module);')
line(out)
line(out, 2, 'return 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, find_jvm_dll, arch, generics,
resources, imports, use_full_names, egg_info, extra_setup_args):
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 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 = open(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':")
if find_jvm_dll:
line(out, 1, "from jcc.windows import add_jvm_dll_directory_to_path")
line(out, 1, "add_jvm_dll_directory_to_path()")
line(out, 1, "import jcc")
line(out, 0, "from . import %s", extname)
else:
line(out, 0, "import os")
line(out, 0, "from . import %s", extname)
line(out)
line(out, 0, '__module_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))
if resources:
def copytree(src, dst):
_dst = os.path.join(modulePath, dst)
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)
else:
shutil.copy2(_src, os.path.join(modulePath, _dst))
package_data.append(_dst)
for resource in resources:
copytree(resource, os.path.split(resource)[-1])
packages = [moduleName]
package = [moduleName]
if modules:
for module in modules:
if os.path.isdir(module):
def copytree(src, dst, is_package):
if is_package:
packages.append('.'.join(package))
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):
package.append(os.path.basename(_src))
copytree(_src, _dst, os.path.exists(os.path.join(_src, '__init__.py')))
package.pop()
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))
package.append(os.path.basename(module))
copytree(module, dst, True)
package.pop()
else:
copytree(module, dst, False)
else:
shutil.copy2(module.rpartition('.')[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 = StringWriter()')
line(out, 2, 'self.getJavaException().printStackTrace(PrintWriter(writer))')
line(out, 2, 'return "\\n".join((str(super(JavaError, self)), " 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(__module_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)
for import_ in imports:
line(out, 0, 'from %s._%s import *', import_.__name__, import_.__name__)
line(out, 0, 'from .%s import *', extname)
if use_full_names:
line(out, 0, 'from java.io import PrintWriter, StringWriter')
out.close()
includes = [os.path.join(output, extname),
os.path.join(jccPath, 'sources')]
for import_ in imports:
includes.append(os.path.join(import_.__module_dir__, 'include'))
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))
if shared:
def copytree(src, dst):
_dst = os.path.join(modulePath, dst)
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)
elif name.endswith('.h'):
shutil.copy2(_src, os.path.join(modulePath, _dst))
package_data.append(_dst)
copytree(os.path.join(output, extname), 'include')
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))
if egg_info:
script_args = ['egg_info']
else:
script_args = ['build_ext']
includes[0:0] = INCLUDES
compile_args = CFLAGS
link_args = LFLAGS
defines=[('PYTHON', None),
('JCC_VER', '"%s"' %(JCC_VER))]
if shared:
defines.append(('_jcc_shared', None))
if generics:
defines.append(('_java_generics', None))
if compiler:
script_args.append('--compiler=%s' %(compiler))
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,
'define_macros': defines
}
if shared:
shlibdir = os.path.dirname(os.path.dirname(_jcc3.__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'] = ['jcc3']
elif sys.platform == 'linux': # distutils no good with -R
args['extra_link_args'] += ['-Wl,-rpath', shlibdir]
args['library_dirs'] = [shlibdir]
args['libraries'] = ['jcc3']
args['extra_link_args'] += [
getattr(import_, "_%s" %(import_.__name__)).__file__
for import_ in imports
]
elif sys.platform == 'win32':
_d = debug and '_d' or ''
libdir = os.path.join(modulePath, 'lib')
if not os.path.exists(libdir):
os.mkdir(libdir)
extlib = os.path.join('lib', "%s%s.lib" %(extname, _d))
package_data.append(extlib)
args['extra_link_args'] += [
os.path.join(shlibdir, 'jcc3', 'jcc3%s.lib' %(_d)),
' '.join(IMPLIB_LFLAGS) %(os.path.join(modulePath, extlib))
]
args['libraries'] = [
os.path.join(import_.__module_dir__, 'lib',
'_%s%s' %(import_.__name__, _d))
for import_ in imports
]
args['define_macros'] += [
("_dll_%s" %(import_.__name__), '__declspec(dllimport)')
for import_ in imports
] + [("_dll_%s" %(moduleName), '__declspec(dllexport)')]
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)]
script_args.extend(extra_setup_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
print("setup args = %s" % args)
setup(**args)