Comments (18)
Just for completeness, I have attached a tar ball (test_case.tar.gz) with a test case in C
and rewritten in Fortran
. The C
code behaves as expected printing (on exiting) the codes of keys pressed and exiting with ESC
. The Fortran
one prints always 0
for the codes and does not exit if not closing the window.
In comment there is the command line used for the build. The compiler is GCC 8.2.0
from fortran-sdl2.
I wonder if a library as SDL2
can be completely interfaced in Fortran
by means of ISO C BINDING
. SDL2
contains C unions
which seem excluded from ISO C BINDING
.
In this page Interoperability of derived types, under point 4, and (here) one can read:
No Fortran type is interoperable with a C union type
, struct type that contains a bit field, or struct type that contains a flexible array member.
Maybe, for confirmation, we need to ask Fortran people...
BTW, just found this discussion.
from fortran-sdl2.
The following code lets you quit the game with the Escape key:
do while (.not. done)
rc = sdl_poll_event(event)
if (rc > 0) then
select case (event%type)
case (SDL_QUIT_TYPE)
done = .true.
case (SDL_KEY_DOWN)
keys = sdl_get_keyboard_state()
! Quit if player hits Escape:
if (keys(SDL_SCANCODE_ESCAPE) == 1) then
done = .true.
end if
end select
end if
end do
Yes, the Fortran standard does not define any unions. But you can use transfer()
to do simple type casting. See sdl_transfer_event()
in sdl2.f90
.
from fortran-sdl2.
@interkosmos wrote:
But you can use transfer() to do simple type casting. See sdl_transfer_event()
Hmm... if sdl_poll_event
already calls sdl_transfer_event()
,
select case (event%type)
! SDL_KeyboardEvent
case (SDL_KEY_DOWN : SDL_KEY_UP)
event%key = transfer(event, event%key)
WHY then
write(*,'(A,i0)') 'KEY = ', event%key%key_sym%sym
prints always 0
?
I tried also
event%key%key_sym%sym = transfer(event, event%key%key_sym%sym)
write(*,'(A,i0)') 'KEY = ', event%key%key_sym%sym
if (event%key%key_sym%sym == ESC) quit = 1
but does not work, prints always 768..
from fortran-sdl2.
@interkosmos wrote:
The following code lets you quit the game with the Escape key:
keys = sdl_get_keyboard_state()
Who is keys
? How it is/must be declared?
Just for completeness, compiling with the -Wall
option your code, prints these warnings:
gfortran -Wall -std=f2008 `sdl2-config --cflags` ../f03sdl2-master/sdl2.f90 draw_test.f90 -o draw_test `sdl2-config --libs`
../f03sdl2-master/sdl2.f90:1469:47:
function sdl_get_render_target(renderer) bind(c, name='SDL_GetRenderTarget')
1
Warning: Unused dummy argument 'renderer' at (1) [-Wunused-dummy-argument]
../f03sdl2-master/sdl2.f90:1469:8:
function sdl_get_render_target(renderer) bind(c, name='SDL_GetRenderTarget')
1
Warning: Return value of function 'sdl_get_render_target' at (1) not set [-Wreturn-type]
draw_test.f90:181:18:
keys = sdl_get_keyboard_state()
1
Warning: POINTER-valued function appears on right-hand side of assignment at (1) [-Wsurprising]
I think sdl_get_render_target
should go in the interface
section not in contains
section of the module:
$ diff -Naur programming/f03sdl2-master/sdl2.f90~ programming/f03sdl2-master/sdl2.f90
--- programming/f03sdl2-master/sdl2.f90~ 2018-09-08 16:19:29.000000000 +0200
+++ programming/f03sdl2-master/sdl2.f90 2018-09-10 01:57:51.391318300 +0200
@@ -977,6 +977,14 @@
integer(kind=c_int) :: sdl_get_system_ram
end function sdl_get_system_ram
+ ! SDL_Texture *SDL_GetRenderTarget(SDL_Renderer *renderer)
+ function sdl_get_render_target(renderer) bind(c, name='SDL_GetRenderTarget')
+ use, intrinsic :: iso_c_binding
+ implicit none
+ type(c_ptr), intent(in), value :: renderer
+ type(c_ptr) :: sdl_get_render_target
+ end function sdl_get_render_target
+
! Uint32 SDL_GetTicks(void)
function sdl_get_ticks() bind(c, name='SDL_GetTicks')
use, intrinsic :: iso_c_binding
@@ -1465,14 +1473,6 @@
call c_f_pointer(surface%format, sdl_get_pixel_format)
end function
- ! SDL_Texture *SDL_GetRenderTarget(SDL_Renderer *renderer)
- function sdl_get_render_target(renderer) bind(c, name='SDL_GetRenderTarget')
- use, intrinsic :: iso_c_binding
- implicit none
- type(c_ptr), intent(in), value :: renderer
- type(c_ptr) :: sdl_get_render_target
- end function sdl_get_render_target
-
! SDL_Surface *SDL_GetWindowSurface(SDL_Window *window)
function sdl_get_window_surface(window)
!! Calls `sdl_get_window_surface_()` and converts the returned
from fortran-sdl2.
OK, I think the code you propose for quitting should be
integer(C_INT8_T), pointer :: keys(:) => null()
[...]
do while (.not. done)
rc = sdl_poll_event(event)
if (rc > 0) then
select case (event%type)
case (SDL_QUIT_TYPE)
done = .true.
case (SDL_KEY_DOWN)
keys => sdl_get_keyboard_state() ! SEE HERE
! Quit if player hits Escape:
if (keys(SDL_SCANCODE_ESCAPE) == 1) then
done = .true.
end if
end select
end if
end do
Notice,
keys => sdl_get_keyboard_state()
an association not an assignement:
keys = sdl_get_keyboard_state()
This change suppress also the warning:
POINTER-valued function appears on right-hand side of assignment
from fortran-sdl2.
Sorry for the incomplete example. The complete one:
integer(kind=8), allocatable :: keys(:)
integer :: rc
do while (.not. is_done)
rc = sdl_poll_event(event)
if (rc > 0) then
select case (event%type)
case (SDL_QUIT_TYPE)
is_done = .true.
case (SDL_KEY_DOWN)
keys = sdl_get_keyboard_state()
! Quit if player hits Escape:
if (is_key(keys, SDL_SCANCODE_ESCAPE)) &
is_done = .true.
end select
end if
end do
The issue with sdl_get_render_target()
was solved already, but not commited. Thank you anyway.
from fortran-sdl2.
I’m still looking for the reason why event%key%key_sym%sym
doesn’t contain the corrent value.
from fortran-sdl2.
@interkosmos, last you code still gives warnings when compiled with -Wall
flag:
gfortran -Wall -std=f2008 `sdl2-config --cflags` ../f03sdl2-master/sdl2.f90 draw_test.f90 -o draw_test `sdl2-config --libs`
draw_test.f90:182:18:
keys = sdl_get_keyboard_state()
1
Warning: POINTER-valued function appears on right-hand side of assignment at (1) [-Wsurprising]
draw_test.f90:182:0:
keys = sdl_get_keyboard_state()
Warning: 'keys.offset' may be used uninitialized in this function [-Wmaybe-uninitialized]
draw_test.f90:182:0: Warning: 'keys.dim[0].lbound' may be used uninitialized in this function [-Wmaybe-uninitialized]
draw_test.f90:182:0: Warning: 'keys.dim[0].ubound' may be used uninitialized in this function [-Wmaybe-uninitialized]
draw_test.f90:182:0:
keys = sdl_get_keyboard_state()
Warning: 'keys.dim[0].lbound' may be used uninitialized in this function [-Wmaybe-uninitialized]
draw_test.f90:182:0: Warning: 'keys.dim[0].ubound' may be used uninitialized in this function [-Wmaybe-uninitialized]
draw_test.f90:182:0: Warning: 'keys.dim[0].ubound' may be used uninitialized in this function [-Wmaybe-uninitialized]
draw_test.f90:182:0: Warning: 'keys.dim[0].lbound' may be used uninitialized in this function [-Wmaybe-uninitialized]
Maybe I am wrong, but I think my proposal
integer(C_INT8_T), pointer :: keys(:) => null()
[...]
keys => sdl_get_keyboard_state()
is the right... (See this at section 11.9)
Any way, may you elaborate about this
OOps, just seen your answer, thanks.
from fortran-sdl2.
Yes, I go d’accord with you. Your proposal seems to be better. See #4 (comment), I’m still clueless.
from fortran-sdl2.
After last change I had to change this code:
integer(C_INT8_T), pointer :: keys(:) => null()
[...]
keys => sdl_get_keyboard_state()
in
integer(C_UINT8_T), pointer :: keys(:) => null()
[...]
! the same
keys => sdl_get_keyboard_state()
The new code build without warnings but does not work, typing ESC
does not exit the program.
Are you sure that in `sdl2_aliases' (why another module and not using the existing sdl2_consts?)
integer, parameter :: c_uint8_t = c_int16_t
is the right thing?
If I remember rightly, Fortran for uint..
types wants int..
types of the same size (int8_t) in this case... but this would break other things, so I think you have to review this carefully...
In other words, uint8_t
in C
is 1 byte
while int16_t
is 2 byte
.
Just this
integer, parameter :: c_uint8_t = c_int8_t
fixes the issue, and maybe also event%key%key_sym%sym
!!!
from fortran-sdl2.
Thank you very much for all the hints. They have been committed.
from fortran-sdl2.
Sorry but there are still some issue. From the SDL2 Wiki:
int SDL_SetRenderDrawColor(SDL_Renderer* renderer,
Uint8 r,
Uint8 g,
Uint8 b,
Uint8 a)
but now I find in your code:
! int SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
function sdl_set_render_draw_color_(renderer, r, g, b, a) bind(c, name='SDL_SetRenderDrawColor')
use, intrinsic :: iso_c_binding
use :: sdl2_consts
implicit none
type(c_ptr), intent(in), value :: renderer
integer(kind=c_uint16_t), intent(in), value :: r
integer(kind=c_uint16_t), intent(in), value :: g
integer(kind=c_uint16_t), intent(in), value :: b
integer(kind=c_uint16_t), intent(in), value :: a
integer(kind=c_int) :: sdl_set_render_draw_color_
end function sdl_set_render_draw_color_
[...]
! int SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
function sdl_set_render_draw_color(renderer, r, g, b, a)
!! Converts integer arguments to c_uint32_t before calling
!! `sdl_set_render_draw_color_()`.
use, intrinsic :: iso_c_binding, only: c_ptr
use :: sdl2_consts
implicit none
type(c_ptr), intent(in) :: renderer
integer, intent(in) :: r
integer, intent(in) :: g
integer, intent(in) :: b
integer, intent(in) :: a
integer :: sdl_set_render_draw_color
sdl_set_render_draw_color = sdl_set_render_draw_color_(renderer, &
int(r, kind=c_uint16_t), &
int(g, kind=c_uint16_t), &
int(b, kind=c_uint16_t), &
int(a, kind=c_uint16_t))
end function sdl_set_render_draw_color
which causes
rc = sdl_set_render_draw_color(renderer,int(r,1),int(g,1),int(b,1), &
1
Error: Type mismatch in argument 'r' at (1); passed INTEGER(1) to INTEGER(4)
If I remember, the previous implementation didn't use the wrapper and maybe it was better. I think the best should be not to use the wrapper
! int SDL_SetRenderDrawColor(SDL_Renderer *renderer, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
function sdl_set_render_draw_color(renderer, r, g, b, a) bind(c, name='SDL_SetRenderDrawColor')
use, intrinsic :: iso_c_binding
use :: sdl2_consts
implicit none
type(c_ptr), intent(in), value :: renderer
integer(kind=c_uint8_t), intent(in), value :: r
integer(kind=c_uint8_t), intent(in), value :: g
integer(kind=c_uint8_t), intent(in), value :: b
integer(kind=c_uint8_t), intent(in), value :: a
integer(kind=c_int) :: sdl_set_render_draw_color
end function sdl_set_render_draw_color
I understand you intent (avoid the explicit conversion by the user), but sometime it would be better to reduce the cost
to call a function to call a function...
from fortran-sdl2.
But how do you want to store an integer like 255 in c_int8_t
? That will cause an arithmetic overflow.
Without a wrapper function, the programmer always has to do the type conversion manually. Boy, that would be annoying.
from fortran-sdl2.
@interkosmos wrote:
But how do you want to store an integer like 255 in c_int8_t?
Have you tried? Why it worked in your previous implementation? In my test case I have color defined with (255,0,127), (255,255,255), (0,255,255)...
and all colors where right..
BTW, I interfaced (most) Windows itself this way without issue.. I think it is how ISO C BINDING works. Maybe we have to ask Fortran people...
Without a wrapper function, the programmer always has to do the type conversion manually. Boy, that would be annoying.
No No.. It is not annoying if you can save the cost of calling function, subroutine... Instead that code not only has the cost of conversion (int(..,kind=...)
) but also one more function call. Any way do at your best.
And... hem hem with last your commit there is this failure:
gfortran -std=f2008 -Wall `sdl2-config --cflags` -o music examples/music/music.f90 sdl2.o sdl2_mixer.o sdl2_ttf.o `sdl2-config --libs` -lSDL2_mixer -lSDL2_ttf
examples/music/music.f90:62:9:
rc = mix_open_audio(MIX_DEFAULT_FREQUENCY, &
1
Error: Type mismatch in argument 'format' at (1); passed INTEGER(4) to INTEGER(2)
make: *** [Makefile:70: music] Error 1
from fortran-sdl2.
Please see the following example:
program example
use, intrinsic :: iso_c_binding
implicit none
integer(kind=c_int8_t) :: foo = int(127, 1) ! works
integer(kind=c_int8_t) :: bar = int(255, 1) ! doesn't work
print *, foo, bar
end program example
IMHO the correct type is therefore c_uint16_t
.
from fortran-sdl2.
Also this work (a solution adopted in 2006 interfacing for the first time BGI aka WinBGIm v. 3):
$ cat print_uint8_t.c
#include <stdio.h>
#include <stdint.h>
void print_uint8_t(uint8_t u)
{
printf("%u\n",u);
}
$ cat test_c_uint8_t.f90
!
! gcc -c print_uint8_t.c
! gfortran -std=f2008 test_c_uint8_t.f90 -o test_c_uint8_t.out print_uint8_t.o
! ./getch_test.out
!
program test_c_uint8_t
implicit none
interface
subroutine print_u8(u) bind(c, name='print_uint8_t')
use, intrinsic :: iso_c_binding, only: C_CHAR
character(C_CHAR), intent(in), value :: u
end subroutine print_u8
end interface
call print_u8(achar(127))
call print_u8(achar(0))
call print_u8(achar(255))
end program test_c_uint8_t
What I don't like is that c_int16_t is 2 byte while in the original C routine the data passed is 1 byte... The C routine takes only the firs byte of it, but I wonder if this is the main street to adopt for this kind of data. I have asked to Fortran people.
Anyway now your example builds fine.. thanks.
from fortran-sdl2.
The first assignment in this chapter is easy: create a program with a main function and a separate subfunction called hello, which when called prints "Hello there!". The subfunction does not take any parameters or return any value, just prints the line. Then, to the main function, add a call to the subfunction and two print commands, the first one before the call which says "Lets call the subfunction:", and one after the subfunction call, a print command which prints "Quitting.". If implemented correctly, the program will print the following:
from fortran-sdl2.
Related Issues (19)
- The Makefile doesn't work HOT 4
- Add Set/Get viewport HOT 3
- Incorrect reference to C procedure HOT 1
- All is broken now HOT 4
- About Final Renaming HOT 1
- Error compiling info example HOT 1
- Segmentation fault for "voxel" example HOT 19
- Some warning with gfortran 10.1 HOT 7
- underscores in function names HOT 2
- The code does not comply with the 2008 standard HOT 9
- catching when sdl_surface (or other types) not defined HOT 2
- SDL2_gfx support HOT 2
- Add the primitive to draw points/pixel HOT 3
- Still warnings after last upgrade HOT 3
- About the SDLK constants HOT 5
- Wrong result with SDLK_SCANCODE_MASK HOT 8
- The mouse wheel does not work on macOS HOT 1
- The `msgbox` example crashes HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from fortran-sdl2.