Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
109ee984
Commit
109ee984
authored
Aug 10, 2009
by
Olivier Aubert
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
python-ctypes: refactor generate.py to be more modular
parent
33043ba3
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
569 additions
and
509 deletions
+569
-509
bindings/python-ctypes/TODO
bindings/python-ctypes/TODO
+0
-11
bindings/python-ctypes/generate.py
bindings/python-ctypes/generate.py
+569
-498
No files found.
bindings/python-ctypes/TODO
View file @
109ee984
...
@@ -4,14 +4,3 @@
...
@@ -4,14 +4,3 @@
* Support multiple VLC versions: define a front-end module which will
* Support multiple VLC versions: define a front-end module which will
load the appropriate versionned module from a subdirectory.
load the appropriate versionned module from a subdirectory.
* Support options: --debug/-c, --output/-o, --check-symbols/-s, ...
* Use setup.py
* Refactor code:
class Parser(list_of_includes) -> properties enums, methods...,
dump()
check()...
class PythonGenerator(parser) -> p.save( filename )
bindings/python-ctypes/generate.py
View file @
109ee984
...
@@ -33,6 +33,7 @@ import re
...
@@ -33,6 +33,7 @@ import re
import
time
import
time
import
operator
import
operator
import
itertools
import
itertools
from
optparse
import
OptionParser
# DefaultDict from ASPN python cookbook
# DefaultDict from ASPN python cookbook
import
copy
import
copy
...
@@ -91,75 +92,16 @@ special_enum_re=re.compile('^(enum)\s*(\S+\s*)?\{\s*(.+)\s*\};')
...
@@ -91,75 +92,16 @@ special_enum_re=re.compile('^(enum)\s*(\S+\s*)?\{\s*(.+)\s*\};')
parameter_passing=DefaultDict(default=1)
parameter_passing=DefaultDict(default=1)
parameter_passing['
libvlc_exception_t
*
']=3
parameter_passing['
libvlc_exception_t
*
']=3
# C-type to ctypes/python type conversion.
class Parser(object):
# Note that enum types conversions are generated (cf convert_enum_names)
def __init__(self, list_of_files):
typ2class={
self.methods=[]
'
libvlc_exception_t
*
': '
ctypes
.
POINTER
(
VLCException
)
',
self.enums=[]
'
libvlc_media_player_t
*
': '
MediaPlayer
',
for name in list_of_files:
'
libvlc_instance_t
*
': '
Instance
',
self.enums.extend(self.parse_typedef(name))
'
libvlc_media_t
*
': '
Media
',
self.methods.extend(self.parse_include(name))
'
libvlc_log_t
*
': '
Log
',
'
libvlc_log_iterator_t
*
': '
LogIterator
',
'
libvlc_log_message_t
*
': '
LogMessage
',
'
libvlc_event_type_t
': '
ctypes
.
c_uint
',
'
libvlc_event_manager_t
*
': '
EventManager
',
'
libvlc_media_discoverer_t
*
': '
MediaDiscoverer
',
'
libvlc_media_library_t
*
': '
MediaLibrary
',
'
libvlc_media_list_t
*
': '
MediaList
',
'
libvlc_media_list_player_t
*
': '
MediaListPlayer
',
'
libvlc_media_list_view_t
*
': '
MediaListView
',
'
libvlc_track_description_t
*
': '
TrackDescription
',
'
libvlc_audio_output_t
*
': '
AudioOutput
',
'
mediacontrol_Instance
*
': '
MediaControl
',
'
mediacontrol_Exception
*
': '
MediaControlException
',
'
mediacontrol_RGBPicture
*
': '
ctypes
.
POINTER
(
RGBPicture
)
',
'
mediacontrol_PlaylistSeq
*
': '
MediaControlPlaylistSeq
',
'
mediacontrol_Position
*
': '
ctypes
.
POINTER
(
MediaControlPosition
)
',
'
mediacontrol_StreamInformation
*
': '
ctypes
.
POINTER
(
MediaControlStreamInformation
)
',
'
WINDOWHANDLE
': '
ctypes
.
c_ulong
',
'
void
': '
None
',
def parse_param(self, s):
'
void
*
': '
ctypes
.
c_void_p
',
'
short
': '
ctypes
.
c_short
',
'
char
*
': '
ctypes
.
c_char_p
',
'
char
**
': '
ListPOINTER
(
ctypes
.
c_char_p
)
',
'
uint32_t
': '
ctypes
.
c_uint
',
'
float
': '
ctypes
.
c_float
',
'
unsigned
': '
ctypes
.
c_uint
',
'
int
': '
ctypes
.
c_int
',
'
...
': '
FIXMEva_list
',
'
libvlc_callback_t
': '
ctypes
.
c_void_p
',
'
libvlc_time_t
': '
ctypes
.
c_longlong
',
}
# Defined python classes, i.e. classes for which we want to generate
# class wrappers around libvlc functions
defined_classes=(
'
MediaPlayer
',
'
Instance
',
'
Media
',
'
Log
',
'
LogIterator
',
#'
LogMessage
',
'
EventManager
',
'
MediaDiscoverer
',
'
MediaLibrary
',
'
MediaList
',
'
MediaListPlayer
',
'
MediaListView
',
'
TrackDescription
',
'
AudioOutput
',
'
MediaControl
',
)
# Definition of prefixes that we can strip from method names when
# wrapping them into class methods
prefixes=dict( (v, k[:-2]) for (k, v) in typ2class.iteritems() if v in defined_classes )
prefixes['
MediaControl
']='
mediacontrol_
'
def parse_param(s):
"""Parse a C parameter expression.
"""Parse a C parameter expression.
It is used to parse both the type/name for methods, and type/name
It is used to parse both the type/name for methods, and type/name
...
@@ -187,65 +129,7 @@ def parse_param(s):
...
@@ -187,65 +129,7 @@ def parse_param(s):
# K&R definition: only type
# K&R definition: only type
return s.replace('
', ''), ''
return s.replace('
', ''), ''
def insert_code(filename):
def parse_typedef(self, name):
"""Generate header/footer code.
"""
f=open(filename, 'r')
for l in f:
if '
build_date
' in l:
print '
build_date
=
"%s"' % time.ctime()
else:
print l,
f.close()
def convert_enum_names(enums):
res={}
for (typ, name, values, comment) in enums:
if typ != '
enum
':
raise Exception('
This
method
only
handles
enums
')
pyname=re.findall('
(
libvlc
|
mediacontrol
)
_
(.
+
?
)(
_t
)
?$
', name)[0][1]
if '
_
' in pyname:
pyname=pyname.title().replace('
_
', '')
elif not pyname[0].isupper():
pyname=pyname.capitalize()
res[name]=pyname
return res
def generate_enums(enums):
for (typ, name, values, comment) in enums:
if typ != '
enum
':
raise Exception('
This
method
only
handles
enums
')
pyname=typ2class[name]
print "class %s(ctypes.c_uint):" % pyname
print '
"""%s
\
n
"""' % comment
conv={}
# Convert symbol names
for k, v in values:
n=k.split('
_
')[-1]
if len(n) == 1:
# Single character. Some symbols use 1_1, 5_1, etc.
n="_".join( k.split('
_
')[-2:] )
if re.match('
^
[
0
-
9
]
', n):
# Cannot start an identifier with a number
n='
_
'+n
conv[k]=n
for k, v in values:
print " %s=%s" % (conv[k], v)
print " _names={"
for k, v in values:
print " %s: '
%
s
'," % (v, conv[k])
print " }"
print """
def __repr__(self):
return ".".join((self.__class__.__module__, self.__class__.__name__, self._names[self.value]))
"""
def parse_typedef(name):
"""Parse include file for typedef expressions.
"""Parse include file for typedef expressions.
This generates a tuple for each typedef:
This generates a tuple for each typedef:
...
@@ -319,7 +203,7 @@ def parse_typedef(name):
...
@@ -319,7 +203,7 @@ def parse_typedef(name):
comment
=
''
comment
=
''
continue
continue
def
parse_include
(
name
):
def
parse_include
(
self
,
name
):
"""Parse include file.
"""Parse include file.
This generates a tuple for each function:
This generates a tuple for each function:
...
@@ -356,11 +240,11 @@ def parse_include(name):
...
@@ -356,11 +240,11 @@ def parse_include(name):
if
m
:
if
m
:
(
ret
,
param
)
=
m
.
groups
()
(
ret
,
param
)
=
m
.
groups
()
rtype
,
method
=
parse_param
(
ret
)
rtype
,
method
=
self
.
parse_param
(
ret
)
params
=
[]
params
=
[]
for
p
in
paramlist_re
.
split
(
param
):
for
p
in
paramlist_re
.
split
(
param
):
params
.
append
(
parse_param
(
p
)
)
params
.
append
(
self
.
parse_param
(
p
)
)
if
len
(
params
)
==
1
and
params
[
0
][
0
]
==
'void'
:
if
len
(
params
)
==
1
and
params
[
0
][
0
]
==
'void'
:
# Empty parameter list
# Empty parameter list
...
@@ -384,10 +268,6 @@ def parse_include(name):
...
@@ -384,10 +268,6 @@ def parse_include(name):
# but it prevented code generation for a minor detail (some bad descriptions).
# but it prevented code generation for a minor detail (some bad descriptions).
params
=
[
(
p
[
0
],
names
[
i
])
for
(
i
,
p
)
in
enumerate
(
params
)
]
params
=
[
(
p
[
0
],
names
[
i
])
for
(
i
,
p
)
in
enumerate
(
params
)
]
for
typ
,
name
in
params
:
if
not
typ
in
typ2class
:
raise
Exception
(
"No conversion for %s (from %s:%s)"
%
(
typ
,
method
,
name
))
# Transform Doxygen syntax into epydoc syntax
# Transform Doxygen syntax into epydoc syntax
comment
=
comment
.
replace
(
'
\
\
param'
,
'@param'
).
replace
(
'
\
\
return'
,
'@return'
)
comment
=
comment
.
replace
(
'
\
\
param'
,
'@param'
).
replace
(
'
\
\
return'
,
'@return'
)
...
@@ -405,7 +285,193 @@ def parse_include(name):
...
@@ -405,7 +285,193 @@ def parse_include(name):
comment
)
comment
)
comment
=
''
comment
=
''
def
output_ctypes
(
rtype
,
method
,
params
,
comment
):
def
dump_methods
(
self
):
print
"** Defined functions **"
for
(
rtype
,
name
,
params
,
comment
)
in
self
.
methods
:
print
"%(name)s (%(rtype)s):"
%
locals
()
for
t
,
n
in
params
:
print
" %(n)s (%(t)s)"
%
locals
()
def
dump_enums
(
self
):
print
"** Defined enums **"
for
(
typ
,
name
,
values
,
comment
)
in
self
.
enums
:
print
"%(name)s (%(typ)s):"
%
locals
()
for
k
,
v
in
values
:
print
" %(k)s=%(v)s"
%
locals
()
class
PythonGenerator
(
object
):
# C-type to ctypes/python type conversion.
# Note that enum types conversions are generated (cf convert_enum_names)
type2class
=
{
'libvlc_exception_t*'
:
'ctypes.POINTER(VLCException)'
,
'libvlc_media_player_t*'
:
'MediaPlayer'
,
'libvlc_instance_t*'
:
'Instance'
,
'libvlc_media_t*'
:
'Media'
,
'libvlc_log_t*'
:
'Log'
,
'libvlc_log_iterator_t*'
:
'LogIterator'
,
'libvlc_log_message_t*'
:
'LogMessage'
,
'libvlc_event_type_t'
:
'ctypes.c_uint'
,
'libvlc_event_manager_t*'
:
'EventManager'
,
'libvlc_media_discoverer_t*'
:
'MediaDiscoverer'
,
'libvlc_media_library_t*'
:
'MediaLibrary'
,
'libvlc_media_list_t*'
:
'MediaList'
,
'libvlc_media_list_player_t*'
:
'MediaListPlayer'
,
'libvlc_media_list_view_t*'
:
'MediaListView'
,
'libvlc_track_description_t*'
:
'TrackDescription'
,
'libvlc_audio_output_t*'
:
'AudioOutput'
,
'mediacontrol_Instance*'
:
'MediaControl'
,
'mediacontrol_Exception*'
:
'MediaControlException'
,
'mediacontrol_RGBPicture*'
:
'ctypes.POINTER(RGBPicture)'
,
'mediacontrol_PlaylistSeq*'
:
'MediaControlPlaylistSeq'
,
'mediacontrol_Position*'
:
'ctypes.POINTER(MediaControlPosition)'
,
'mediacontrol_StreamInformation*'
:
'ctypes.POINTER(MediaControlStreamInformation)'
,
'WINDOWHANDLE'
:
'ctypes.c_ulong'
,
'void'
:
'None'
,
'void*'
:
'ctypes.c_void_p'
,
'short'
:
'ctypes.c_short'
,
'char*'
:
'ctypes.c_char_p'
,
'char**'
:
'ListPOINTER(ctypes.c_char_p)'
,
'uint32_t'
:
'ctypes.c_uint'
,
'float'
:
'ctypes.c_float'
,
'unsigned'
:
'ctypes.c_uint'
,
'int'
:
'ctypes.c_int'
,
'...'
:
'FIXMEva_list'
,
'libvlc_callback_t'
:
'ctypes.c_void_p'
,
'libvlc_time_t'
:
'ctypes.c_longlong'
,
}
# Defined python classes, i.e. classes for which we want to generate
# class wrappers around libvlc functions
defined_classes
=
(
'MediaPlayer'
,
'Instance'
,
'Media'
,
'Log'
,
'LogIterator'
,
'EventManager'
,
'MediaDiscoverer'
,
'MediaLibrary'
,
'MediaList'
,
'MediaListPlayer'
,
'MediaListView'
,
'TrackDescription'
,
'AudioOutput'
,
'MediaControl'
,
)
def
__init__
(
self
,
parser
=
None
):
self
.
parser
=
parser
# Generate python names for enums
self
.
type2class
.
update
(
self
.
convert_enum_names
(
parser
.
enums
))
self
.
check_types
()
# Definition of prefixes that we can strip from method names when
# wrapping them into class methods
self
.
prefixes
=
dict
(
(
v
,
k
[:
-
2
])
for
(
k
,
v
)
in
self
.
type2class
.
iteritems
()
if
v
in
self
.
defined_classes
)
self
.
prefixes
[
'MediaControl'
]
=
'mediacontrol_'
def
save
(
self
,
filename
=
None
):
if
filename
is
None
or
filename
==
'-'
:
self
.
fd
=
sys
.
stdout
else
:
self
.
fd
=
open
(
filename
,
'w'
)
self
.
insert_code
(
'header.py'
)
self
.
generate_enums
(
self
.
parser
.
enums
)
wrapped_methods
=
self
.
generate_wrappers
(
self
.
parser
.
methods
)
for
l
in
self
.
parser
.
methods
:
self
.
output_ctypes
(
*
l
)
self
.
insert_code
(
'footer.py'
)
all_methods
=
set
(
t
[
1
]
for
t
in
self
.
parser
.
methods
)
not_wrapped
=
all_methods
.
difference
(
wrapped_methods
)
self
.
output
(
"# Not wrapped methods:"
)
for
m
in
not_wrapped
:
self
.
output
(
"# "
,
m
)
if
self
.
fd
!=
sys
.
stdout
:
self
.
fd
.
close
()
def
output
(
self
,
*
p
):
self
.
fd
.
write
(
" "
.
join
(
p
))
self
.
fd
.
write
(
"
\
n
"
)
def
check_types
(
self
):
"""Make sure that all types are properly translated.
This method must be called *after* convert_enum_names, since
the latter populates type2class with converted enum names.
"""
for
(
rt
,
met
,
params
,
c
)
in
self
.
parser
.
methods
:
for
typ
,
name
in
params
:
if
not
typ
in
self
.
type2class
:
raise
Exception
(
"No conversion for %s (from %s:%s)"
%
(
typ
,
met
,
name
))
def
insert_code
(
self
,
filename
):
"""Generate header/footer code.
"""
f
=
open
(
filename
,
'r'
)
for
l
in
f
:
if
'build_date'
in
l
:
self
.
output
(
'build_date="%s"'
%
time
.
ctime
())
else
:
self
.
output
(
l
.
rstrip
())
f
.
close
()
def
convert_enum_names
(
self
,
enums
):
res
=
{}
for
(
typ
,
name
,
values
,
comment
)
in
enums
:
if
typ
!=
'enum'
:
raise
Exception
(
'This method only handles enums'
)
pyname
=
re
.
findall
(
'(libvlc|mediacontrol)_(.+?)(_t)?$'
,
name
)[
0
][
1
]
if
'_'
in
pyname
:
pyname
=
pyname
.
title
().
replace
(
'_'
,
''
)
elif
not
pyname
[
0
].
isupper
():
pyname
=
pyname
.
capitalize
()
res
[
name
]
=
pyname
return
res
def
generate_enums
(
self
,
enums
):
for
(
typ
,
name
,
values
,
comment
)
in
enums
:
if
typ
!=
'enum'
:
raise
Exception
(
'This method only handles enums'
)
pyname
=
self
.
type2class
[
name
]
self
.
output
(
"class %s(ctypes.c_uint):"
%
pyname
)
self
.
output
(
' """%s
\
n
"""'
%
comment
)
conv
=
{}
# Convert symbol names
for
k
,
v
in
values
:
n
=
k
.
split
(
'_'
)[
-
1
]
if
len
(
n
)
==
1
:
# Single character. Some symbols use 1_1, 5_1, etc.
n
=
"_"
.
join
(
k
.
split
(
'_'
)[
-
2
:]
)
if
re
.
match
(
'^[0-9]'
,
n
):
# Cannot start an identifier with a number
n
=
'_'
+
n
conv
[
k
]
=
n
for
k
,
v
in
values
:
self
.
output
(
" %s=%s"
%
(
conv
[
k
],
v
))
self
.
output
(
" _names={"
)
for
k
,
v
in
values
:
self
.
output
(
" %s: '%s',"
%
(
v
,
conv
[
k
]))
self
.
output
(
" }"
)
self
.
output
(
"""
def __repr__(self):
return ".".join((self.__class__.__module__, self.__class__.__name__, self._names[self.value]))
"""
)
def
output_ctypes
(
self
,
rtype
,
method
,
params
,
comment
):
"""Output ctypes decorator for the given method.
"""Output ctypes decorator for the given method.
"""
"""
if
method
in
blacklist
:
if
method
in
blacklist
:
...
@@ -413,10 +479,10 @@ def output_ctypes(rtype, method, params, comment):
...
@@ -413,10 +479,10 @@ def output_ctypes(rtype, method, params, comment):
return
return
if
params
:
if
params
:
print
"prototype=ctypes.CFUNCTYPE(%s, %s)"
%
(
typ
2class
.
get
(
rtype
,
'FIXME_%s'
%
rtype
),
self
.
output
(
"prototype=ctypes.CFUNCTYPE(%s, %s)"
%
(
self
.
type
2class
.
get
(
rtype
,
'FIXME_%s'
%
rtype
),
","
.
join
(
typ2class
[
p
[
0
]]
for
p
in
params
))
","
.
join
(
self
.
type2class
[
p
[
0
]]
for
p
in
params
)
))
else
:
else
:
print
"prototype=ctypes.CFUNCTYPE(%s)"
%
typ2class
.
get
(
rtype
,
'FIXME_%s'
%
rtype
)
self
.
output
(
"prototype=ctypes.CFUNCTYPE(%s)"
%
self
.
type2class
.
get
(
rtype
,
'FIXME_%s'
%
rtype
)
)
if
not
params
:
if
not
params
:
...
@@ -425,15 +491,15 @@ def output_ctypes(rtype, method, params, comment):
...
@@ -425,15 +491,15 @@ def output_ctypes(rtype, method, params, comment):
flags
=
"paramflags=( (%d, ), )"
%
parameter_passing
[
params
[
0
][
0
]]
flags
=
"paramflags=( (%d, ), )"
%
parameter_passing
[
params
[
0
][
0
]]
else
:
else
:
flags
=
"paramflags=%s"
%
","
.
join
(
'(%d,)'
%
parameter_passing
[
p
[
0
]]
for
p
in
params
)
flags
=
"paramflags=%s"
%
","
.
join
(
'(%d,)'
%
parameter_passing
[
p
[
0
]]
for
p
in
params
)
print
flags
self
.
output
(
flags
)
print
'%s = prototype( ("%s", dll), paramflags )'
%
(
method
,
method
)
self
.
output
(
'%s = prototype( ("%s", dll), paramflags )'
%
(
method
,
method
)
)
if
'3'
in
flags
:
if
'3'
in
flags
:
# A VLCException is present. Process it.
# A VLCException is present. Process it.
print
"%s.errcheck = check_vlc_exception"
%
method
self
.
output
(
"%s.errcheck = check_vlc_exception"
%
method
)
print
'%s.__doc__ = """%s"""'
%
(
method
,
comment
)
self
.
output
(
'%s.__doc__ = """%s"""'
%
(
method
,
comment
)
)
print
self
.
output
()
def
parse_override
(
name
):
def
parse_override
(
self
,
name
):
"""Parse override definitions file.
"""Parse override definitions file.
It is possible to override methods definitions in classes.
It is possible to override methods definitions in classes.
...
@@ -470,7 +536,7 @@ def parse_override(name):
...
@@ -470,7 +536,7 @@ def parse_override(name):
return code, overridden_methods, docstring
return code, overridden_methods, docstring
def fix_python_comment(
c):
def fix_python_comment(self,
c):
"""Fix comment by removing first and last parameters (self and exception)
"""Fix comment by removing first and last parameters (self and exception)
"""
"""
data=c.replace('
@
{
', '').replace('
@
see
', '
See
').splitlines()
data=c.replace('
@
{
', '').replace('
@
see
', '
See
').splitlines()
...
@@ -485,32 +551,32 @@ def fix_python_comment(c):
...
@@ -485,32 +551,32 @@ def fix_python_comment(c):
return "
\
n
".join(itertools.chain(body, param, ret))
return "
\
n
".join(itertools.chain(body, param, ret))
def generate_wrappers(
methods):
def generate_wrappers(self,
methods):
"""Generate class wrappers for all appropriate methods.
"""Generate class wrappers for all appropriate methods.
@return: the set of wrapped method names
@return: the set of wrapped method names
"""
"""
ret=set()
ret=set()
# Sort methods against the element they apply to.
# Sort methods against the element they apply to.
elements=sorted( ( (typ
2class.get(params[0][0]), rt, met, params, c)
elements=sorted( ( (self.type
2class.get(params[0][0]), rt, met, params, c)
for (rt, met, params, c) in methods
for (rt, met, params, c) in methods
if params and typ2class.get(params[0][0], '
_
') in
defined_classes
if params and self.type2class.get(params[0][0], '
_
') in self.
defined_classes
),
),
key=operator.itemgetter(0))
key=operator.itemgetter(0))
overrides, overriden_methods, docstring=
parse_override('
override
.
py
')
overrides, overriden_methods, docstring=self.
parse_override('
override
.
py
')
for classname, el in itertools.groupby(elements, key=operator.itemgetter(0)):
for classname, el in itertools.groupby(elements, key=operator.itemgetter(0)):
print """class %(name)s(object):""" % {'
name
': classname}
self.output("""class %(name)s(object):""" % {'
name
': classname})
if classname in docstring:
if classname in docstring:
print '
"""%s
\
n
"""' % docstring[classname]
self.output('
"""%s
\
n
"""' % docstring[classname])
print
"""
self.output(
"""
def __new__(cls, pointer=None):
def __new__(cls, pointer=None):
'''Internal method used for instanciating wrappers from ctypes.
'''Internal method used for instanciating wrappers from ctypes.
'''
'''
if pointer is None:
if pointer is None:
raise Exception("Internal method. You should instanciate objects through other class methods (probably named '
new
' or ending with '
new
')
")
raise Exception("Internal method. Surely this class cannot be instanciated by itself.
")
if pointer == 0:
if pointer == 0:
return None
return None
else:
else:
...
@@ -523,12 +589,12 @@ def generate_wrappers(methods):
...
@@ -523,12 +589,12 @@ def generate_wrappers(methods):
'''(INTERNAL) ctypes parameter conversion method.
'''(INTERNAL) ctypes parameter conversion method.
'''
'''
return arg._as_parameter_
return arg._as_parameter_
""" % {'
name
': classname}
""" % {'
name
': classname})
if classname in overrides:
if classname in overrides:
print overrides[classname]
self.output(overrides[classname])
prefix=
prefixes.get(classname, '')
prefix=self.
prefixes.get(classname, '')
for cl, rtype, method, params, comment in el:
for cl, rtype, method, params, comment in el:
if method in blacklist:
if method in blacklist:
...
@@ -547,64 +613,69 @@ def generate_wrappers(methods):
...
@@ -547,64 +613,69 @@ def generate_wrappers(methods):
else:
else:
args=", ".join( p[1] for p in params )
args=", ".join( p[1] for p in params )
print " def %s(%s):" % (name, args
)
self.output(" def %s(%s):" % (name, args)
)
print '
"""%s
\
n
"""' % fix_python_comment(comment
)
self.output('
"""%s
\
n
"""' % self.fix_python_comment(comment)
)
if params and params[-1][0] == '
libvlc_exception_t
*
':
if params and params[-1][0] == '
libvlc_exception_t
*
':
# Exception handling
# Exception handling
print " e=VLCException()"
self.output(" e=VLCException()")
print " return %s(%s, e)" % (method, args
)
self.output(" return %s(%s, e)" % (method, args)
)
elif params and params[-1][0] == '
mediacontrol_Exception
*
':
elif params and params[-1][0] == '
mediacontrol_Exception
*
':
# Exception handling
# Exception handling
print " e=MediaControlException()"
self.output(" e=MediaControlException()")
print " return %s(%s, e)" % (method, args
)
self.output(" return %s(%s, e)" % (method, args)
)
else:
else:
print " return %s(%s)" % (method, args
)
self.output(" return %s(%s)" % (method, args)
)
print
self.output()
# Check for standard methods
# Check for standard methods
if name == '
count
':
if name == '
count
':
# There is a count method. Generate a __len__ one.
# There is a count method. Generate a __len__ one.
print " def __len__(self):"
self.output(""" def __len__(self):
print " e=VLCException()"
e=VLCException()
print " return %s(self, e)" % method
return %s(self, e)
print
""" % method)
elif name.endswith('
item_at_index
'):
elif name.endswith('
item_at_index
'):
# Indexable (and thus iterable)"
# Indexable (and thus iterable)"
print " def __getitem__(self, i):"
self.output(""" def __getitem__(self, i):
print " e=VLCException()"
e=VLCException()
print " return %s(self, i, e)" % method
return %s(self, i, e)
print
print " def __iter__(self):"
def __iter__(self):
print " e=VLCException()"
e=VLCException()
print " for i in xrange(len(self)):"
for i in xrange(len(self)):
print " yield self[i]"
yield self[i]
print
""" % method)
return ret
return ret
def process(output, list_of_includes):
p=Parser(list_of_includes)
g=PythonGenerator(p)
g.save(output)
if __name__ == '
__main__
':
if __name__ == '
__main__
':
enums=[]
opt=OptionParser(usage="""Parse VLC include files and generate bindings code.
for name in sys.argv[1:]:
%prog [options] include_file.h [...]""")
enums.extend(list(parse_typedef(name)))
# Generate python names for enums
typ2class.update(convert_enum_names(enums))
methods=[]
opt.add_option("-d", "--debug", dest="debug", action="store_true",
for name in sys.argv[1:]:
default=False,
methods.extend(list(parse_include(name)))
help="Debug mode")
if debug:
sys.exit(0)
insert_code('
header
.
py
')
opt.add_option("-o", "--output", dest="output", action="store",
generate_enums(enums)
type="str", default="-",
wrapped=generate_wrappers(methods)
help="Output filename")
for l in methods:
output_ctypes(*l)
insert_code('
footer
.
py
')
all=set( t[1] for t in methods )
(options, args) = opt.parse_args()
not_wrapped=all.difference(wrapped)
print "# Not wrapped methods:"
if not args:
for m in not_wrapped:
opt.print_help()
print "# ", m
sys.exit(1)
p=Parser(args)
if options.debug:
p.dump_methods()
p.dump_enums()
sys.exit(0)
g=PythonGenerator(p)
g.save(options.output)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment