My real life program uses integer*8 variables and does not compile with this specific iso_c_binding patch, see below. My program works fine when the iso_c_binding package is not used.
With the iso_c_binding package in my program, I get the following error message:
Error: Type mismatch in argument 'test_variable' at (1); passed INTEGER(8) to TYPE(c_ptr)
I’ve created the below testcase from my program. My program cannot be published. The testcase demonstrates the error that I’m getting.
Question 1: How do you fix this? The following is what I would like if at all possible! The two structs in the test.c file actually exist in my program. The game function formal arguments also actually exist in my real world program. My program passes integer*8 variables to the game routine. Everything else besides these three things should be able to be modified.
Other Questions: Does the C code have to change? Not counting the iso_c_binding interface code, does the Fortran code have to change? What has to change?
Can iso_c_binding do this?
Thank you,
File the_game.f
module the_game
use, intrinsic :: iso_c_binding, only: c_int, c_float, c_ptr
type, bind(c) :: myfloat
real(c_float) :: float_tmp
end type
type, bind(c) :: myint
integer(c_int) :: int_tmp
end type
interface
function game(myint1, myfloat2) bind(c, name="game_")
import :: c_int, c_ptr
implicit none
type(c_ptr) :: myint1
type(c_ptr) :: myfloat2
integer(c_int) :: game
end function
end interface
end module the_game
File main.f:
program main
use the_game
integer*8 test_variable
integer*8 test_variable2
integer ans
ans=game (test_variable,test_variable2)
end program main
File test.c:
#include <stdio.h>
struct myfloat
{
float float_tmp;
};
struct myint
{
int int_tmp;
};
int game_(myint1,myfloat2)
struct myint **myint1;
struct myfloat **myfloat2;
{
/* printf ("(*myint1)->int_tmp = %d\n",(*myint1)->int_tmp); */
/* printf ("(*myfloat2)->float_tmp = %f\n",(*myfloat2)->float_tmp); */
/* (*myint1)->int_tmp = 1; */
/* (*myfloat2)->float_tmp = 100.1; */
return(0);
}
Compilation:
gcc -g -c test.c -o test.o
gfortran -g -c the_game.f -o the_game.o
gfortran -g -c main.f -o main.o
gfortran -g main.o test.o -o main.exe -lgfortran
Output:
main.f:9.19:
ans=game (test_variable,test_variable2)
1
Error: Type mismatch in argument 'myint1' at (1); passed INTEGER(8) to TYPE(c_ptr)
Alternative 1: The following main.f doesn't work:
Reference: https://wiki.scorec.rpi.edu/wiki/Iso_c_binding
program main
use the_game
integer*8, allocatable, target :: test_variable1
integer*8, allocatable, target :: test_variable2
integer ans
type(c_ptr) :: cptr1
type(c_ptr) :: cptr2
allocate (test_variable1)
allocate (test_variable2)
cptr1 = c_loc(test_variable1)
cptr2 = c_loc(test_variable2)
ans=game (cptr1,cptr2)
end program main
Output:
main.f:14.17:
cptr1 = c_loc(test_variable1)
1
Error: Can't convert REAL(4) to TYPE(c_ptr) at (1)
main.f:15.17:
cptr2 = c_loc(test_variable2)
1
Error: Can't convert REAL(4) to TYPE(c_ptr) at (1)
Alternative 2: The following main.f doesn't work when uncomment test.c:
File main.f:
program main
use the_game
TYPE(c_ptr) test_variable
TYPE(c_ptr) test_variable2
integer ans
ans=game (test_variable,test_variable2)
end program main
#include <stdio.h>
struct myfloat
{
float float_tmp;
};
struct myint
{
int int_tmp;
};
int game_(myint1,myfloat2)
struct myint **myint1;
struct myfloat **myfloat2;
{
/*printf ("(*myint1)->int_tmp = %d\n",(*myint1)->int_tmp);
printf ("(*myfloat2)->float_tmp = %f\n",(*myfloat2)->float_tmp);
(*myint1)->int_tmp = 1;
(*myfloat2)->float_tmp = 2.0;*/
return(0);
}
Run of Executable if uncomment 4 statements in test.c: Last statement in test.c causing seg fault:
Program received signal SIGSEGV: Segmentation fault - invalid memory reference. line 5: 3541 Segmentation fault ./main.exe
Alternative 3: The following main.f change to the code doesn't work:
File main.f:
program main
use the_game
integer*8 test_variable
integer*8 test_variable2
integer ans
type(c_ptr) :: cptr1
type(c_ptr) :: cptr2
cptr1=c_loc(test_variable1)
cptr2=c_loc(test_variable2)
test_variable1 = 90
test_variable2 = 1000
ans=game (cptr1,cptr2)
end program main
Compilation:
main.f:11.25:
cptr1=c_loc(test_variable1)
1
Error: Can't convert REAL(4) to TYPE(c_ptr) at (1)
main.f:12.26:
cptr2=c_loc(test_variable2)
1
Error: Can't convert REAL(4) to TYPE(c_ptr) at (1)
Alternative 4: The following main.f change to the code doesn't compile:
program main
use iso_c_binding
use the_game
TYPE(c_ptr) test_variable
TYPE(c_ptr) test_variable2
integer*8 value1
integer*8 value2
integer ans
test_variable=c_loc(value1)
test_variable2=c_loc(value2)
ans=game (test_variable,test_variable2)
end program main
Compilation Error:
main.f:12.31:
test_variable=c_loc(value1)
1
Error: Parameter 'value1' to 'c_loc' at (1) must be either a TARGET or an associated pointer
main.f:13.32:
test_variable2=c_loc(value2)
1
Error: Parameter 'value2' to 'c_loc' at (1) must be either a TARGET or an associated pointer