1. FFI question for Gregg

Hi Gregg

Andy's SDL2 wrapper worked in the first version but unfortunately I seem to be getting an out of memory error. Not sure if there was something I was missing. Here's a bare minimum program that demos the issue.

--minimal setup to demo memory issue with ffi 
--uses SDL, but will just get relevant structure created 
 
include std/ffi.e 
include std/machine.e 
include std/math.e 
 
 
public constant SDL_RELEASED = 0 
public constant SDL_PRESSED = 1 
 
public enum type SDL_EventType 
	SDL_FIRSTEVENT     = 0,    -- /**< Unused (do not remove) */ 
 
    
    SDL_QUIT           = 0x100, --/**< User-requested quit */ 
 
    --/* These application events have special meaning on iOS, see README-ios.md for details */ 
    SDL_APP_TERMINATING,       -- /**< The application is being terminated by the OS 
                                --     Called on iOS in applicationWillTerminate() 
                                --     Called on Android in onDestroy() 
                               -- */ 
    SDL_APP_LOWMEMORY,         -- /**< The application is low on memory, free memory if possible. 
                               --      Called on iOS in applicationDidReceiveMemoryWarning() 
                               --      Called on Android in onLowMemory() 
                               -- */ 
    SDL_APP_WILLENTERBACKGROUND,-- /**< The application is about to enter the background 
                                 --    Called on iOS in applicationWillResignActive() 
                                 --    Called on Android in onPause() 
                                --*/ 
    SDL_APP_DIDENTERBACKGROUND, --/**< The application did enter the background and may not get CPU for some time 
                                  --   Called on iOS in applicationDidEnterBackground() 
                                  --   Called on Android in onPause() 
                                --*/ 
    SDL_APP_WILLENTERFOREGROUND, --/**< The application is about to enter the foreground 
                                   --  Called on iOS in applicationWillEnterForeground() 
                                   --  Called on Android in onResume() 
                                --*/ 
    SDL_APP_DIDENTERFOREGROUND, --/**< The application is now interactive 
                                 --    Called on iOS in applicationDidBecomeActive() 
                                 --    Called on Android in onResume() 
                               -- */ 
 
    SDL_LOCALECHANGED,   
 
    
    SDL_DISPLAYEVENT   = 0x150,   
 
    
    SDL_WINDOWEVENT    = 0x200, 
    SDL_SYSWMEVENT,              
 
    SDL_KEYDOWN        = 0x300,  
    SDL_KEYUP,                   
    SDL_TEXTEDITING,             
    SDL_TEXTINPUT,               
    SDL_KEYMAPCHANGED,     
      
    SDL_TEXTEDITING_EXT,        
 
   
    SDL_MOUSEMOTION    = 0x400,  
    SDL_MOUSEBUTTONDOWN,         
    SDL_MOUSEBUTTONUP,          
    SDL_MOUSEWHEEL,              
 
    
    SDL_JOYAXISMOTION  = 0x600,  
    SDL_JOYBALLMOTION,           
    SDL_JOYHATMOTION,            
    SDL_JOYBUTTONDOWN,          
    SDL_JOYBUTTONUP,             
    SDL_JOYDEVICEADDED,          
    SDL_JOYDEVICEREMOVED,        
    SDL_JOYBATTERYUPDATED,     
 
     
    SDL_CONTROLLERAXISMOTION  = 0x650,  
    SDL_CONTROLLERBUTTONDOWN,           
    SDL_CONTROLLERBUTTONUP,             
    SDL_CONTROLLERDEVICEADDED,         
    SDL_CONTROLLERDEVICEREMOVED,       
    SDL_CONTROLLERDEVICEREMAPPED,       
    SDL_CONTROLLERTOUCHPADDOWN,       
    SDL_CONTROLLERTOUCHPADMOTION,       
    SDL_CONTROLLERTOUCHPADUP,          
    SDL_CONTROLLERSENSORUPDATE,         
 
   
    SDL_FINGERDOWN      = 0x700, 
    SDL_FINGERUP, 
    SDL_FINGERMOTION, 
 
    
    SDL_DOLLARGESTURE   = 0x800, 
    SDL_DOLLARRECORD, 
    SDL_MULTIGESTURE, 
 
  
    SDL_CLIPBOARDUPDATE = 0x900,  
 
     
    SDL_DROPFILE        = 0x1000,  
    SDL_DROPTEXT,                 
    SDL_DROPBEGIN,               
    SDL_DROPCOMPLETE,              
 
    
    SDL_AUDIODEVICEADDED = 0x1100,  
    SDL_AUDIODEVICEREMOVED,         
 
     
    SDL_SENSORUPDATE = 0x1200,      
 
     
    SDL_RENDER_TARGETS_RESET = 0x2000,  
    SDL_RENDER_DEVICE_RESET,  
 
   
    SDL_POLLSENTINEL = 0x7F00,  
 
    --/** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use, 
     --*  and should be allocated with SDL_RegisterEvents() 
     --*/ 
    SDL_USEREVENT    = 0x8000, 
 
    --/** 
    -- *  This last event is only for bounding internal arrays 
    -- */ 
    SDL_LASTEVENT    = 0xFFFF 
end type 
 
public constant SDL_CommonEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32 --timestamp 
}) 
 
public constant SDL_DisplayEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_UINT32, --display 
	C_UINT8, --event 
	--C_UINT8, --padding1 
	--C_UINT8, --padding2 
	--C_UINT8, --padding3 
	C_INT32 --data1 
}) 
 
public constant SDL_WindowEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_UINT32, --windowID 
	C_UINT8, --event 
	--C_UINT8, --padding1 
	--C_UINT8, --padding2 
	--C_UINT8, --padding3 
	C_INT32, --data1 
	C_INT32 --data2 
}) 
 
public constant SDL_KeyboardEvent = define_c_struct({ 
	C_UINT32, --type [1] 
	C_UINT32, --timestamp [2] 
	C_UINT32, --windowID [3] 
	C_UINT8, --state [4] 
	C_UINT8 --repeat [5] 
	--C_UINT8, --padding2 [6] 
	--C_UINT8, --padding3 [7] 
	--SDL_Keysym --key that was pressed or released [8] 
}) 
 
public constant SDL_TEXTEDITINGEVENT_TEXT_SIZE = 32 
 
public constant SDL_TextEditingEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_UINT32, --windowID 
	C_CHAR, --text 
	C_INT32, --start 
	C_INT32 --length 
}) 
 
public constant SDL_TextEditingExtEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_UINT32, --windowID 
	C_STRING, --text 
	C_INT32, --start 
	C_INT32 --length 
}) 
 
public constant SDL_TEXTINPUTEVENT_TEXT_SIZE = 32 
 
public constant SDL_TextInputEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_UINT32, --windowID 
	C_CHAR --text 
}) 
 
public constant SDL_MouseMotionEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_UINT32, --windowID 
	C_UINT32, --which 
	C_INT32, --x 
	C_INT32, --y 
	C_INT32, --xrel 
	C_INT32 --yrel 
}) 
 
public constant SDL_MouseButtonEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_UINT32, --windowID 
	C_UINT32, --which 
	C_UINT8, --button 
	C_UINT8, --state 
	C_UINT8, --clicks 
	C_UINT8, --padding1 
	C_INT32, --x 
	C_INT32 --y 
}) 
 
public constant SDL_MouseWheelEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_UINT32, --windowID 
	C_UINT32, --which 
	C_INT32, --x 
	C_INT32, --y 
	C_UINT32, --direction 
	C_FLOAT, --precisex 
	C_FLOAT, --precisey 
	C_INT32, --mouseX 
	C_INT32 --mouseY 
}) 
 
public constant SDL_JoyAxisEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --joystick id which 
	C_UINT8, --axis 
	C_UINT8, --padding1 
	C_UINT8, --padding2 
	C_UINT8, --padding3 
	C_INT16, --value 
	C_UINT16 --padding4 
}) 
 
public constant SDL_JoyBallEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --joystick id which 
	C_UINT8, --ball 
	C_UINT8, --padding1 
	C_UINT8, --padding2 
	C_UINT8, --padding3 
	C_INT16, --xrel 
	C_INT16 --yrel 
}) 
 
public constant SDL_JoyHatEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --joystick id which 
	C_UINT8, --hat 
	C_UINT8, --value 
	C_UINT8, --padding1 
	C_UINT8 --padding2 
}) 
 
public constant SDL_JoyButtonEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --joystick id which 
	C_UINT8, --button 
	C_UINT8, --state 
	C_UINT8, --padding1 
	C_UINT8 --padding2 
}) 
 
public constant SDL_JoyDeviceEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_INT32 --which 
}) 
 
public constant SDL_JoyBatteryEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --joystick which 
	C_INT --joystick powerlevel 
}) 
 
public constant SDL_ControllerAxisEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --joystickid which 
	C_UINT8, --axis 
	--C_UINT8, --padding1 
	--C_UINT8, --padding2 
	--C_UINT8, --padding3 
	C_INT16, --value 
	C_UINT16 --padding4 
}) 
 
public constant SDL_ControllerButtonEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --joystickid which 
	C_UINT8, --button 
	C_UINT8, --state 
	C_UINT8, --padding1 
	C_UINT8 --padding2 
}) 
 
public constant SDL_ControllerDeviceEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_INT32 --which 
}) 
 
public constant SDL_ControllerTouchpadEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --joystickid which 
	C_INT32, --touchpad 
	C_INT32, --finger 
	C_FLOAT, --x 
	C_FLOAT, --y 
	C_FLOAT --pressure 
}) 
 
public constant SDL_ControllerSensorEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --joystickid which 
	C_INT32, --sensor 
	{C_FLOAT,3}, --data (array of 3) 
	C_UINT64 --timestamp of sensor reading in microseconds, if hardware supports info 
}) 
 
public constant SDL_AudioDeviceEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_UINT32, --which 
	C_UINT8, --icapture 
	C_UINT8, --padding1 
	C_UINT8, --padding2 
	C_UINT8 --padding3 
}) 
 
public constant SDL_TouchFingerEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --touchID 
	C_LONG, --fingerID 
	C_FLOAT, --x 
	C_FLOAT, --y 
	C_FLOAT, --dx 
	C_FLOAT, --dy 
	C_FLOAT, --pressure 
	C_UINT32 --windowID 
}) 
 
public constant SDL_MultiGestureEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --touchID 
	C_FLOAT, --dTheta 
	C_FLOAT, --dDist 
	C_FLOAT, --x 
	C_FLOAT, --y 
	C_UINT16, --numFingers 
	C_UINT16 --padding 
}) 
 
public constant SDL_DollarGestureEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_LONG, --touchID 
	C_LONG, --gestureID 
	C_UINT32, --numFingers 
	C_FLOAT, --error 
	C_FLOAT, --x 
	C_FLOAT --y 
}) 
 
public constant SDL_DropEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_POINTER, --file 
	C_UINT32 --windowID 
}) 
 
public constant SDL_SensorEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_INT32, --which 
	{C_FLOAT,6}, --data 
	C_UINT64 --timestamp of sensor reading in microseconds 
}) 
 
public constant SDL_QuitEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32 --timestamp 
}) 
 
public constant SDL_OSEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32 --timestamp 
}) 
 
public constant SDL_UserEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_UINT32, --windowID 
	C_INT32, --code 
	C_POINTER, --data1 
	C_POINTER --data2 
}) 
 
public constant SDL_SysWMEvent = define_c_struct({ 
	C_UINT32, --type 
	C_UINT32, --timestamp 
	C_POINTER --msg 
}) 
 
 
--=================================================================== 
public constant SDL_Event = define_c_struct({ 
	C_UINT32, --type [1] 
	SDL_CommonEvent, --[2] 
	SDL_DisplayEvent, --[3] 
	SDL_WindowEvent, --[4] 
	SDL_KeyboardEvent, --[5] 
	SDL_TextEditingEvent, --[6] 
	SDL_TextEditingExtEvent, --[7] 
	SDL_TextInputEvent, --[8] 
	SDL_MouseMotionEvent, --[9] 
	SDL_MouseButtonEvent, --[10] 
	SDL_MouseWheelEvent, --[11] 
	SDL_JoyAxisEvent, --[12] 
	SDL_JoyBallEvent, --[13] 
	SDL_JoyHatEvent, --[14] 
	SDL_JoyButtonEvent, --[15] 
	SDL_JoyDeviceEvent, --[16] 
	SDL_JoyBatteryEvent, --[17] 
	SDL_ControllerAxisEvent, --[18] 
	SDL_ControllerButtonEvent, --[19] 
	SDL_ControllerDeviceEvent, --[20] 
	SDL_ControllerTouchpadEvent, --[21] 
	SDL_ControllerSensorEvent, --[22] 
	SDL_AudioDeviceEvent, --[23] 
	SDL_SensorEvent, --[24] 
	SDL_QuitEvent, --[25] 
	SDL_UserEvent, --[26] 
	SDL_SysWMEvent, --[27] 
	SDL_TouchFingerEvent, --[28] 
	SDL_MultiGestureEvent, --[29] 
	SDL_DollarGestureEvent, --[30] 
	SDL_DropEvent --[31] 
}) 
 
 
 
atom event_ptr = allocate_struct(SDL_Event) 
atom event_type 
 

produces the error

1795457776 
couldn't alloc 1795457776 bytes 
 
C:\EuProgramming\Euphoria4_1\libffi-euphoria\include\std\ffi.e:780 in function a 
llocate_struct() 
Your program has run out of memory. 
One moment please... 

I made some small mods to you ffi.e

public function allocate_mem(atom block_size) 
    return machine_func( M_ALLOC, block_size ) 
end function 
 
public procedure free(atom mem) 
    return machine_func( M_FREE, mem ) 
end procedure 
 
/*,ade the followin small changes 

34 - public added to constant declaration 
262 - public function allocate_string( sequence s, integer cleanup = 0 ) 
    --abd made public 
	atom mem = machine_func( M_ALLOC, length(s) + 1 ) 
 
	if mem then 
		poke( mem, s ) 
		poke( mem+length(s), 0 ) 
	end if 
 
    if cleanup then end if 
 
	return mem 
end function 
-- added cleanup for compatabilty with eu 
--added pubic functions allocate_mem and free 
*/ 

but I can't see how these would be an issue.

Anyway, ideas?

Cheers

Chris

new topic     » topic index » view message » categorize

2. Re: FFI question for Gregg

I got the same error when I tried renaming the variables myself. So I went back to the old version of FFI. Its probably an easy fix. Might have to do with the 32 and 64-bit versions of the DLLs. Or something to do with how 32-bit and 64-bit memory is handled.

new topic     » goto parent     » topic index » view message » categorize

3. Re: FFI question for Gregg

ChrisB said...

Andy's SDL2 wrapper worked in the first version but unfortunately I seem to be getting an out of memory error. Not sure if there was something I was missing. Here's a bare minimum program that demos the issue.

(snip)

produces the error

1795457776 
couldn't alloc 1795457776 bytes 
 
C:\EuProgramming\Euphoria4_1\libffi-euphoria\include\std\ffi.e:780 in function a 
llocate_struct() 
Your program has run out of memory. 
One moment please... 

Good catch! That was definitely a bug. When creating a copy of the C_POINTER type for C_STRING it incorrectly overwrote the copied data with default values and this caused it to try and allocate a pointer's value worth of bytes. (Oops.) I've corrected in now. See commit #cfbf236.

Very important! Make sure you are now using define_c_union() for union types. This ensures the members "collapse" correctly so they all start at zero offset. Then use the nested types in the union to "typecast" the union when you peek/poke the members (see my example below). If you use define_c_struct() each of the members will be aligned sequentially in memory which is not what you want. You can see this if you print the sizeof() result. On my system (64-bit Ubuntu) using define_c_union() the sizeof(SDL_Event) is 24 bytes but using define_c_struct() the sizeof(SDL_Event) is 800 bytes!

-- declare the union 
public constant SDL_Event = define_c_union({ 
    C_UINT32, --type [1] 
--  (lots of types here) 
}) 
 
-- allocate the memory 
atom event = allocate_struct( SDL_Event ) 
 
-- (event loop or something here) 
 
-- "typecast" the union to SDL_CommonEvent to get common members 
atom eventtype = peek_member( event, SDL_CommonEvent, 1 ) 
atom timestamp = peek_member( event, SDL_CommonEvent, 2 ) 
 
if eventtype = SDL_DISPLAYEVENT then 
 
    -- "typecast" the union to SDL_DisplayEvent to read its members 
    atom displayid = peek_member( event, SDL_DisplayEvent, 3 ) 
    atom dispevent = peek_member( event, SDL_DisplayEvent, 4 ) 
 
elsif eventtype = SDL_WINDOWEVENT then 
 
    -- "typecast" the union to SDL_WindowEvent to read its members 
    atom windowid = peek_member( event, SDL_WindowEvent, 3 ) 
    atom winevent = peek_member( event, SDL_WindowEvent, 4 ) 
 
elsif eventtype = SDL_KEYDOWN or eventtype = SDL_KEYUP then 
 
    -- "typecast" the union to SDL_KeyboardEvent to read its members 
    atom windowid  = peek_member( event, SDL_KeyboardEvent, 3 ) 
    atom keystate  = peek_member( event, SDL_KeyboardEvent, 4 ) 
	atom keyrepeat = peek_member( event, SDL_KeyboardEvent, 5 ) 
 
else -- etc. 
 
end if 
 
free( event ) 
ChrisB said...

I made some small mods to you ffi.e

(snip)

but I can't see how these would be an issue.

Don't bother modifying any of the boilerplate code inside of std/ffi.e. It's only there because I need to be keep std/ffi.e free of include statements to ensure my code doesn't inherit any side-effects from (or cause any side-effects to) the standard library. Once this goes into Euphoria all of that will go away and I will be using the standard library routines again. You should just use std/machine.e, std/types.e, etc.

-Greg

new topic     » goto parent     » topic index » view message » categorize

4. Re: FFI question for Gregg

Thanks for the help, Greg. I've updated my SDL 2 wrapper with the new define_c_struct and define_c_union types. I did test and the example programs were working.

new topic     » goto parent     » topic index » view message » categorize

5. Re: FFI question for Gregg

Thanks.

Cheers

Chris

new topic     » goto parent     » topic index » view message » categorize

6. Re: FFI question for Gregg

Hi Gregg

FFI's definition of allocate_string takes one parameter, and the std's definition takes two,

 
ffi - allocate_string(sequence string) 
 
std - allocate_string(sequence string, boolean clean) 
 

Chris

new topic     » goto parent     » topic index » view message » categorize

7. Re: FFI question for Gregg

ChrisB said...

FFI's definition of allocate_string takes one parameter, and the std's definition takes two,

 
ffi - allocate_string(sequence string) 
 
std - allocate_string(sequence string, boolean clean) 
 

Sure, but the distinction is irrelevant. The code in std/ffi.e that allocates strings always calls free() on them later. If I had a cleanup parameter it would never get used. It's not meant to be a complete replacement for the standard library function; it's just enough to avoid repeating myself. The places where that is used will end up in the backend which uses its own C methods for allocating strings.

-Greg

new topic     » goto parent     » topic index » view message » categorize

8. Re: FFI question for Gregg

Hi

The distinction arises when it's called, and there are two parameters, an error is thrown complaining about too many parameters. I realise that the same thing happens (as far as allocate_string), hence why I put 'if clean then end if' in there. The functionality is still the same, in that the second parameter if used is just discarded.

Thanks for all this work by the way.

Cheers

Chris

new topic     » goto parent     » topic index » view message » categorize

9. Re: FFI question for Gregg

ChrisB said...

The distinction arises when it's called, and there are two parameters, an error is thrown complaining about too many parameters. I realise that the same thing happens (as far as allocate_string), hence why I put 'if clean then end if' in there. The functionality is still the same, in that the second parameter if used is just discarded.

My point is that you shouldn't even be seeing it and you shouldn't care that it's there. When you include std/ffi.e its version of allocate_string() is not public so you'll never see it. Just leave it alone and use std/machine.e if you need allocate_string().

-Greg

new topic     » goto parent     » topic index » view message » categorize

10. Re: FFI question for Gregg

Ah, ok.

Cheers

Chris

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu