I would like to call a C api function from Fortran. The C function accepts an array of bytes:
void image(const void *bitmap, int w, int h);
where three successive bytes in *bitmap
represent an RGB colour tripple and are interpreted as unsigned char
in C. I want to initialize the bitmap in Fortran and take care of drawing inside C. Current definition in Fortran uses
integer*1 rgbImage(6,2)
to initialize an image of 2x2 for example, but compiler won't accept assignment
rgbImage(1,1) = 255
to get red colour. I've seen hints of using BYTE
, UNSIGNED*1
, LOGICAL*1
for unsigned single bytes, but gfortran (MacPort's gcc 4.4 or 4.6 under Mac OS X) isn't really happy with either of them. I could probably get away by cheating and assigning value -1
instead of 255
, but that is very uncomfortable to use. The compiler flag -fno-range-check
helped compile the code, but might not be available in other Fortran compilers and I consider it an ugly solution (I would still want to catch other warning). The values 'FF'X
or '11111111'B
are also recognized as 32-bit integers.
It is highly desirable for the code to be portable across different Fortran compilers.
4-byte values (word, int) If we combine 4 bytes, we get a value with 32 bits, which can store 65536*65536 distinct values. This gives a range of approximately 4 billion different values. In many languages, a data type referred to simply as an "int" (=integer) is assumed to be 4 bytes.
REAL*16 (Quad Real) @ (SPARC only) The REAL*16 data type is a quadruple-precision real. The size for a REAL*16 item is 16 bytes.
My suggestion would be to use CHARACTER
variables, and use ACHAR
to set values (and ICHAR
to convert back to integers as necessary). That should get you what you want and be completely portable. eg,
character, dimension(6,2) :: rgbImage
rgbImage(1,1) = achar(255)
Updated to add: if you're going to use the Fortran 2003 iso_c_binding stuff to interface to the C routines (highly recommended!) then you might as well make that rgbImage array characters of kind c_char
, eg
character(kind=c_char), dimension(6,2) :: rgbImage
integer(kind=c_int) :: w, h
...
rgbImage(1,1) = achar(255)
...
call image(rgbImage, w, h)
where you've defined the interface for the routine
interface
subroutine image(img, w, h) bind(C)
use, intrinsic :: iso_c_binding
implicit none
integer(kind=c_int), intent(in), value :: w, h
character(kind=c_char) :: img(:,:)
end subroutine image
end interface
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With