Question

I am writing a module in c for a fortran program and I need to pass some strings to the fortran program. I am unable to modify the fortran code, but can write my own fortran code to call the existing code. I have tried googling this and there are a lot of different approaches written at a level that I don't understand.

The c string is of variable length (although it's set before being passed). The fortran "string" is declared as character*(*), so I don't see the length that the character array needs to be padded to. Here's some code fragments to see what I need to do.

c function that I'm writing:

void c_func(int db_handle) {
  char *geom_name;
  int geom_handle = 0;

  size_t geom_name_len = db_get_len(db_handle); !gets the length of the name
  geom_name = (char *)malloc(sizeof(char*(geom_name_len+1)));
  db_pull(db_handle, geom_name); !pulls geom_name from db as a null terminated string
  call_fortan_function(geom_handle, geom_name); !The fortran function will set the integer
  ...}

fortran function that I can't modify does some stuff with the name and then sets a value to the handle:

logical function f_fn(handle, name)

integer handle
character*(*) name

I assume the best way to do this will be to create a separate c function that parses geom_name into some stuff that fortran will use and then a fortran function to create the fortran string and pass it to the function that I can't change, but I don't know how to do that. Any help?

Was it helpful?

Solution

You cannot portably call Fortran procedure requiring character(*) from C. It is not possible, because the procedure takes typically another argument defining the string length. You may try to guess it's format, probably it is additional int as a last argument.

I would make another Fortran wrapper, that would take an int with length and an array of chars of length length preferably without the trailing \0.

logical function f_wrap(handle, name, length) bind(C,name="f_wrap")
  use iso_c_binding
  integer(c_int),value :: handle
  integer(c_int),value :: length
  character(1,kind=c_char),intent(in) :: name(length)
  character(length) :: tmp

  tmp = name
  f_wrap = f_fn(int(handle), tmp)
end function

The tmp may be unnecessary, because the binary representation is the same, just try it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top