forked from kivy/python-for-android
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjava2python.py
More file actions
102 lines (83 loc) · 2.71 KB
/
java2python.py
File metadata and controls
102 lines (83 loc) · 2.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import sys
import subprocess
def parse_signature(java, jni):
if not jni.startswith(' Signature: '):
print 'invalid signature'
return
jni = jni[13:]
javas = java.split()
if javas[0] in ('public', 'private', 'protected'):
javas.pop(0)
is_static = False
if javas[0] == 'static':
javas.pop(0)
is_static = True
if jni[0] == '(':
if javas[0][0] == '{':
return
if javas[0] in ('public', 'private', 'protected'):
javas.pop(0)
# method
if '(' in javas[0]:
# constructor
return ('constructor', '', jni)
else:
javas.pop(0)
name = javas[0].split('(')[0]
if is_static:
return ('staticmethod', name, jni)
return ('method', name, jni)
else:
# field
if javas[0] in ('public', 'private', 'protected'):
javas.pop(0)
name = javas[1].split(';')[0]
if is_static:
return ('staticfield', name, jni)
return ('field', name, jni)
def parse(filename):
cmd = subprocess.Popen(['javap', '-s', filename], stdout=subprocess.PIPE)
stdout = cmd.communicate()[0]
lines = stdout.splitlines()[1:]
line = lines.pop(0)
if not line.startswith('public class') and not line.startswith('class'):
print '-> not a public class, exit.'
return []
javaclass = line[13:].split('{')[0].split(' ')[0]
pythonclass = javaclass.rsplit('.')[-1]
members = []
while len(lines) > 2:
javasignature = lines.pop(0)
jnisignature = lines.pop(0)
member = parse_signature(javasignature, jnisignature)
if member is None:
continue
members.append(member)
return (javaclass, pythonclass, members)
def generate(defs):
javaclass, pythonclass, members = defs
output = '''
from java import MetaJavaClass, JavaClass, JavaMethod, \\
JavaStaticMethod, JavaField, JavaStaticField
class {0!r}(JavaClass):
__metaclass__ = MetaJavaClass
__javaclass__ = '{1!r}'
'''.format(pythonclass, javaclass)
pyclasses = {
'method': 'JavaMethod',
'staticmethod': 'JavaStaticMethod',
'field': 'JavaField',
'staticfield': 'JavaStaticField' }
for member in members:
tp, name, sig = member
if tp == 'constructor':
output += ' __javaconstructor__ = {0!r}\n'.format(sig)
continue
cls = pyclasses[tp]
output += ' {0} = {1}({2!r})\n'.format(name, cls, sig)
return output
if __name__ == '__main__':
filename = sys.argv[1]
if filename.endswith('.class'):
filename = filename[:-6]
print generate(parse(filename))