I have a c program that looks as following:
using namespace std;
extern"C" {
void fortfunc_(int a[][4], int *size_x, int *size_y);
}
int main()
{
// size_x and size_y are dynamically determined at runtime
// setting them here directly for simplification
int size_x = 5;
int size_y = 4;
//we need to use 4 instead of size_y to prevent a mismatch with the int a[][4] definition in fortfunc_
int foo [size_x][4];
for (int i=0 ; i<size_x ; i )
{
for (int y=0 ; y<size_y ; y )
{
foo[i][y] = i y;
}
}
fortfunc_(foo, &size_x, &size_y);
return 0;
}
The respective fortran program only prints the array and looks like this:
subroutine fortfunc(foo, size_x, size_y)
use :: ISO_C_BINDING
integer :: size_x, size_y
integer(c_int), dimension(size_y,size_x), intent(in) :: foo
integer :: i, y
do y = 1, size_x ! We reverse the loop order because of the reverse array order in fortran
do i = 1, size_y
print*, "col ",i,y, foo(i,y)
end do
print*, "row"
end do
return
end
When compiled with gfortran -c testF.f90 && g -c testC.cpp && g -o test testF.o testC.o -lgfortran && ./test
this works.
However, I would like to be able to dynamically determine the shape of the 2d array foo
in my main
function and call my external fortfunc_
function accordingly, instead of hardcoding int a[][4]
there. How can I modify my program to accomplish that?
CodePudding user response:
You typically allocate a 1d vector and treat it as a 2d array.
Example:
#include <vector>
extern "C" {
// note the changed signature with `int* a` instead:
void fortfunc_(int* a, int *size_x, int *size_y);
}
int main() {
int size_x = 5;
int size_y = 4;
// A 1d vector with size_y * size_x elements:
std::vector<int> foo(size_y * size_x);
for (int y = 0; y < size_y; y ) {
for (int x = 0; x < size_x; x ) {
// calculation for row-major order:
foo[y * size_x x] = y * size_x x;
// Note: Fortran uses column-major order so you may need to change
// to `foo[x * size_y y] = x * size_y y;`
}
}
fortfunc_(foo.data(), &size_x, &size_y);
// ^^^^^^
// a pointer to the first `int` in the 1d vector
}
Output:
col 1 1 0
col 2 1 1
col 3 1 2
col 4 1 3
row
col 1 2 4
col 2 2 5
col 3 2 6
col 4 2 7
row
col 1 3 8
col 2 3 9
col 3 3 10
col 4 3 11
row
col 1 4 12
col 2 4 13
col 3 4 14
col 4 4 15
row
col 1 5 16
col 2 5 17
col 3 5 18
col 4 5 19
row