Llamar a una subrutina FORTRAN desde C

Estoy tratando de llamar a una función FORTRAN desde C

Mis preguntas son:

  1. Si fortRoutine es el nombre de mi subrutina fortran, entonces estoy llamando a esto de C como fortRoutine_ . Si fortRoutine contiene solo un argumento de matriz de caracteres, entonces puedo pasar de esta manera:

     fortRoutine_("I am in fortran"); 
  2. Al llamar a las subrutinas de FORTRAN, ¿cuándo debo usar pasar por valor y cuándo pasar por referencia?

Como soy nuevo en C, no tengo ni idea sobre esto. Si es posible, sugiera algunos buenos enlaces de tutoriales también.

La forma de hacer esto ahora es usar la unión Fortran ISO C en el lado de Fortran. Esto es parte del estándar de lenguaje Fortran 2003 y está disponible en muchos comstackdores; no es específico de gcc. Se ha descrito en muchas respuestas en este sitio. Como parte del estándar de lenguaje, es comstackdor y plataforma independiente. Y no necesita conocer las convenciones internas de aprobación del comstackdor. El enlace ISO C, cuando se usa en la statement de una subrutina o función de Fortran, hace que el comstackdor Fortran use las convenciones de llamadas C para que el procedimiento pueda ser llamado directamente desde C. No necesita agregar argumentos ocultos ni nombrar mangle Nombre de la subrutina Fortran, es decir, sin guiones bajos. El nombre utilizado por el vinculador proviene de la opción “vincular”.

Las cadenas son un caso difícil porque técnicamente en C son matrices de caracteres y tienes que unir esto en el Fortran. También tiene que tratar con las diferentes definiciones de cadenas: C es nulo terminado, Fortran de longitud fija y acolchado con espacios en blanco. El ejemplo muestra cómo funciona esto. Los números son más fáciles. El único problema con las matrices es que C es row-major y Fortran column-major para que las matrices multidimensionales se transpongan.

 int main ( void ) { char test [10] = "abcd"; myfortsub (test); return 0; } 

y

 subroutine myfortsub ( input_string ) bind ( C, name="myfortsub" ) use iso_c_binding, only: C_CHAR, c_null_char implicit none character (kind=c_char, len=1), dimension (10), intent (in) :: input_string character (len=10) :: regular_string integer :: i regular_string = " " loop_string: do i=1, 10 if ( input_string (i) == c_null_char ) then exit loop_string else regular_string (i:i) = input_string (i) end if end do loop_string write (*, *) ">", trim (regular_string), "<", len_trim (regular_string) return end subroutine myfortsub 

Comstacks el C a un archivo de objeto y usas gfortran para comstackr el fortran y vincular ambos:

 gcc-mp-4.6 \ -c \ test_fortsub.c gfortran-mp-4.6 \ test_fortsub.o \ myfortsub.f90 \ -o test_fortsub.exe 

La salida es:

  >abcd< 4 

Por supuesto, todo esto depende de tu comstackdor FORTRAN, pero en general:

  1. No, necesitarás pasar un argumento de longitud oculta para tu cadena. Algunos comstackdores intercalan estos con los otros parámetros, directamente después de la cadena. Otros, agrupan todos los argumentos de longitud de cadena al final de la lista de argumentos.

     char str[11] = {0}; fortranFunc_(str, sizeof(str) - 1); // remember that 'str' will need to be null terminated // and will be padding with spaces to fit the length // so for C passing strings to Fortran specify the length // less 1 so you can add a nul terminator, and on all strings // being filled in by FORTRAN, trim-end all spaces. 
  2. Casi siempre se pasa por referencia, pero puede alternar este comportamiento usando atributos en los argumentos ficticios en el lado de FORTRAN.

     int value = 10; fortranFunc_(&value); // INTEGER I 

Aquí hay algunas referencias, que son aplicables en base a varios comstackdores:

  • Interoperabilidad FORTRAN / C
  • gfortran – Interoperabilidad con C
  • Intel Fortran – Interoperabilidad con C
  • El módulo ISO_C_BINDING

La respuesta depende del comstackdor y del sistema (técnicamente, su ABI). Para GCC (que es un C, un C ++, un Ada y un comstackdor Fortran), lea el capítulo de progtwigción mixta de Fortran .