size_t in Fortran

I believe that size_t interoperable type in Fortran is INTEGER(c_size_t). If I use a C function which accepts an integer of type size_t.
If this function is called in C code, we can pass an integer constant or an integer variable of type int without any error.
However, when I call it from Fortran, it doesn’t allow me to pass a variable of type INTEGER, i.e. it requires the variable to be of the same KIND and TYPE also.

Example: C function:

integer foofunc(size_t abc)

Fortran binding

function foofunc(abc) BIND(C, NAME=“foofunc”) result (res)
INTEGER(c_size_t), value :: abc
INTEGER(c_int) :: res
end function

Suppose that I already have the variable abc of type INTEGER, if I pass abc to the function

INTEGER :: abc
abc = ...
res = foofunc(abc)

I get error

GF90-S-0450-Argument number 1 to foofunc: kind mismatch

Is it the only way that I have to create a new variable, say abc_prime

INTEGER(c_size_t) :: abc_prime
abc_prime = abc

and pass abc_prime to the function.
This is not good if abc is not a scalar but an array. I don’t want to create a duplicate of it. Is there an alternative way that I can do something in Fortran similar to type cast in C.

Thanks,
Tuan

Hi,

There are a few issues:

  1. By default, fortran passes argument by reference. You wrote foofunc in a way that it takes arguments by value. You will need to write an interface for foofunc so that it gets arguments by value correctly.

  2. If you decide to pass it by value, I am not sure how you are going to pass array.

You may need to decide to change your C code to take argument by reference instead of by passing by value. Then you can pass array in your Fortran code.

Hongyon

Thanks, Hongyon. I understand the difference between passing as reference and value. However, you haven’t give me the answer for my question. That is, how to pass a Fortran data to a C function, without making a duplicate of the data. If you know a solution, could you please give me small example to do that, passing by reference or value is okay.

Thanks,
Tuan

Take a look at equivalence statement. It might help in your case. You will need to be extra careful if it is an array because this is memory equivalence.

Hongyon

Thanks, Hongyon. Is EQUIVALENCE applicable to (array) data on device memory or we can only use it with host memory.

Tuan.

Hi Tuan,

Looking at the original kind mismatch error, I believe the problem is that “size_t” is a 64-bit integer in 64-bits and a 32-bit integer in 32-bits. Hence, ABC should be declared as an INTEGER*8 in 64-bits and INTEGER in 32-bits.

% cat test.f90
program en
use iso_c_binding
integer :: A
integer :: B

interface
function foofunc(abc) BIND(C, NAME="foofunc") result (res)
use iso_c_binding
INTEGER(c_size_t), value :: abc
INTEGER(c_int) :: res
end function
end interface

A=1
B=foofunc(A)

end program en
% pgf90 -c test.f90 -m64
PGF90-S-0450-Argument number 1 to foofunc: kind mismatch (test.f90: 15)
  0 inform,   0 warnings,   1 severes, 0 fatal for en
% pgf90 -c test.f90 -m32
% pgf90 -c test.f90 -m64 -i8
%



Is EQUIVALENCE applicable to (array) data on device memory or we can only use it with host memory.

Right now it’s only valid with host variables. Though we are looking at adding it for CUDA Fortran device variables as well.

  • Mat

Great! Thanks Mat.

Tuan.