Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- '''
- Joystick RSDL Extension, by Brett
- goatman.py@gmail.com
- license BSD
- Interfacing RPython with C
- The documentation on how to interface RPython with C is rather limited, the extending doc mentions that `MixedModules` using rffi is the most advanced method available. The rffi document only provides a quick glance at how to use rffi.llexternal. The best place to get started is looking at the source code in rlib/rsdl/RSDL.py which binds RPython to SDL. What should be clear after reading RSDL.py is that PyPy provides a very direct and easy to understand interface for C; that should also provide the highest possible performance.
- The source code in rffi_platform.py (found in pypy/rpython/tool) is very interesting, it generates dynamic C code that it compiles to get information about the C code we are trying to wrap, for example if you had used the wrong name in a struct it will generate an error. Using rffi_platform different C types can be defined, such as structs, constant integers; these are then put into a special container class called CConfig, which is then parsed by rffi_platform.configure(CConfig) and wrappers returned. After we have the wrappers we must tell any pointers we had previously used in the CConfig that they `become` those objects, MyPointer.TO.become(MyStruct).
- RSDL that is included in PyPy is incomplete and lacks wrappers for Joystick, the code below wraps SDL Joystick.
- '''
- PATH2PYPY = 'pypy'
- import sys, math, time
- sys.path.append(PATH2PYPY)
- from pypy.rlib.objectmodel import specialize
- from pypy.rpython.lltypesystem import lltype, rffi
- from pypy.rpython.tool import rffi_platform as platform
- from pypy.rlib.rsdl import RSDL, RSDL_helper
- from pypy.rlib.rsdl.eci import get_rsdl_compilation_info
- eci = get_rsdl_compilation_info()
- ## wrapper for rffi.llexternal just to shorten the call
- def external(name, args, result): return rffi.llexternal(name, args, result, compilation_info=eci)
- JoystickPtr = lltype.Ptr(lltype.ForwardReference())
- JoyAxisEventPtr = lltype.Ptr(lltype.ForwardReference())
- JoyBallEventPtr = lltype.Ptr(lltype.ForwardReference())
- JoyButtonEventPtr = lltype.Ptr(lltype.ForwardReference())
- JoyHatEventPtr = lltype.Ptr(lltype.ForwardReference())
- class CConfig:
- _compilation_info_ = eci
- Joystick = platform.Struct('SDL_JoyAxisEvent', []) # just and ID, struct contains nothing
- # rsdl/constants.py already defines SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, etc..
- JoyAxisEvent = platform.Struct('SDL_JoyAxisEvent',
- [('type', rffi.INT),
- ('which', rffi.INT),
- ('axis', rffi.INT),
- ('value', rffi.INT)])
- JoyBallEvent = platform.Struct('SDL_JoyBallEvent',
- [('type', rffi.INT),
- ('which', rffi.INT),
- ('ball', rffi.INT),
- ('xrel', rffi.INT), ('yrel', rffi.INT)])
- JoyButtonEvent = platform.Struct('SDL_JoyButtonEvent',
- [('type', rffi.INT),
- ('which', rffi.INT),
- ('button', rffi.INT),
- ('state', rffi.INT)]) # SDL_PRESSED or SDL_RELEASED
- JoyHatEvent = platform.Struct('SDL_JoyHatEvent',
- [('type', rffi.INT),
- ('which', rffi.INT),
- ('hat', rffi.INT),
- ('value', rffi.INT)]) # SDL_HAT_*
- CONSTS = 'INIT_JOYSTICK QUERY ENABLE IGNORE PRESSED RELEASED'
- #hat already in rsdl/constants.py#HAT_CENTERED HAT_UP HAT_RIGHT HAT_DOWN HAT_LEFT HAT_RIGHTUP HAT_RIGHTDOWN HAT_LEFTUP HAT_LEFTDOWN'
- for name in CONSTS.split():
- name = name.strip()
- if name:
- ci = platform.ConstantInteger('SDL_%s' %name)
- setattr( CConfig, name, ci )
- globals().update(platform.configure(CConfig))
- JoystickPtr.TO.become(Joystick)
- JoyAxisEventPtr.TO.become(JoyAxisEvent)
- JoyBallEventPtr.TO.become(JoyBallEvent)
- JoyButtonEventPtr.TO.become(JoyButtonEvent)
- JoyHatEventPtr.TO.become(JoyHatEvent)
- #Updates the state(position, buttons, etc.) of all open joysticks.
- #If joystick events have been enabled with SDL_JoystickEventState then this is called automatically in the event loop.
- JoystickUpdate = external('SDL_JoystickUpdate', [], lltype.Void)
- NumJoysticks = external('SDL_NumJoysticks', [], rffi.INT)
- ## CCHARP seems to stand for C char pointer ##
- JoystickName = external('SDL_JoystickName', [rffi.INT], rffi.CCHARP)
- JoystickOpen = external('SDL_JoystickOpen', [rffi.INT], JoystickPtr)
- JoystickOpened = external('SDL_JoystickOpened', [rffi.INT], rffi.INT)
- JoystickIndex = external('SDL_JoystickIndex', [JoystickPtr], rffi.INT)
- JoystickNumAxes = external('SDL_JoystickNumAxes', [JoystickPtr], rffi.INT)
- JoystickNumBalls = external('SDL_JoystickNumBalls', [JoystickPtr], rffi.INT)
- JoystickNumHats = external('SDL_JoystickNumHats', [JoystickPtr], rffi.INT)
- JoystickNumButtons = external('SDL_JoystickNumButtons', [JoystickPtr], rffi.INT)
- JoystickGetAxis = external('SDL_JoystickGetAxis', [JoystickPtr,rffi.INT], rffi.INT) # 16bit signed integer (-32768 to 32768)
- JoystickGetHat = external('SDL_JoystickGetHat', [JoystickPtr,rffi.INT], rffi.INT) # Uint8
- JoystickGetButton = external('SDL_JoystickGetButton', [JoystickPtr,rffi.INT], rffi.INT) # Uint8
- # is this correct?
- #JoystickBallXPtr = lltype.Ptr(lltype.ForwardReference())
- #JoystickBallYPtr = lltype.Ptr(lltype.ForwardReference())
- #int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy);
- #JoystickGetBall = external('SDL_JoystickGetBall', [JoystickPtr,rffi.INT, JoystickBallXPtr, JoystickBallYPtr], rffi.INT) # Uint8
- JoystickClose = external('SDL_JoystickClose', [JoystickPtr], lltype.Void) # Uint8
- #This function is used to enable or disable joystick event processing. With joystick event processing disabled you will have to update joystick states with SDL_JoystickUpdate and read the joystick information manually. state is either SDL_QUERY, SDL_ENABLE or SDL_IGNORE.
- JoystickEventState = external('SDL_JoystickEventState', [rffi.INT], rffi.INT)
- def handle_event( etype, event ):
- if etype == RSDL.JOYAXISMOTION:
- p = rffi.cast( JoyAxisEventPtr, event )
- axis = rffi.getintfield(p, 'c_axis')
- value = rffi.getintfield(p, 'c_value')
- print 'axis: %s value: %s' %(axis, value)
- elif etype == RSDL.JOYBALLMOTION:
- p = rffi.cast( JoyBallEventPtr, event )
- ball = rffi.getintfield(p, 'c_ball')
- x = rffi.getintfield(p, 'c_xrel')
- y = rffi.getintfield(p, 'c_yrel')
- print 'ball: %s x: %s y: %s' %(ball, x,y)
- elif etype == RSDL.JOYHATMOTION:
- p = rffi.cast( JoyHatEventPtr, event )
- hat = rffi.getintfield(p, 'c_hat')
- value = rffi.getintfield(p, 'c_value')
- print 'hat: %s value: %s' %(hat, value)
- elif etype in ( RSDL.JOYBUTTONDOWN, RSDL.JOYBUTTONUP ):
- p = rffi.cast( JoyButtonEventPtr, event )
- but = rffi.getintfield(p, 'c_button')
- state = rffi.getintfield(p, 'c_state')
- print 'button: %s state: %s' %(but, state)
- def poll(loops=1000):
- event = lltype.malloc(RSDL.Event, flavor='raw')
- try:
- i = 1
- while i < loops:
- ok = RSDL.PollEvent(event); ok = rffi.cast(lltype.Signed, ok)
- assert ok >= 0
- if ok > 0: c_type = rffi.getintfield(event, 'c_type'); handle_event( c_type, event )
- time.sleep(0.01)
- i += 1
- finally: lltype.free(event, flavor='raw')
- def test():
- assert RSDL.Init(INIT_JOYSTICK | RSDL.INIT_VIDEO ) >= 0
- num = NumJoysticks(); print 'number of joysticks/gamepads: %s' %num
- JoystickEventState( RSDL.ENABLE )
- if num:
- joy = JoystickOpen( 0 )
- numaxes = JoystickNumAxes( joy ); print 'number of axes: %s' %numaxes
- numbut = JoystickNumButtons( joy ); print 'number of buttons: %s' %numbut
- poll()
- if __name__ == '__main__':
- from pypy.translator.interactive import Translation
- t = Translation( test )
- t.annotate(); t.rtype()
- entrypoint = t.compile_c()
- entrypoint()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement