2012-03-13 8 views
11

Escribo código que llamará a una función C de Fortran utilizando el mecanismo de interoperabilidad C de Fortran (introducido en Fortran 2003 e implementado en las versiones más nuevas de gfortran e ifort).Matrices de cadenas en puentes Fortran-C usando iso_c_binding

This answer es casi lo que necesito, pero yo no puedo sacarlo de mi cabeza lo que la declaración de interfaz que debe utilizar en Fortran para una función C que tiene este aspecto:

int use_array(int n, char * array[]){ 
    int i; 
    for(i=0; i<n; i++){ 
     printf("Item %d = %s\n",i,array[i]); 
    } 
    return n; 
} 

No me queda claro lo que la declaración debe ser para la interfaz en el extremo Fortran:

interface 
    function use_array(n, x) bind(C) 
     use iso_c_binding 
     integer (c_int) use_array 
     integer (c_int), value :: n 
     character(c_char) WHAT_SHOULD_GO_HERE? :: x 
    end function use_array 
end interface 

sí sé que voy a tener que lidiar con el problema de terminación nula también.

+0

Muchas gracias por francescalus de usuario para la edición amablemente esta pregunta para que me parecen menos educados mediante la eliminación de un "gracias" al final de la misma. Gracias a Dios que usuarios como ellos están cerca para evitar que las personas hagan preguntas ilegibles con cortesía cotidiana. – JoeZuntz

Respuesta

8

La forma en que lo hacemos es utilizar una matriz C_PTR para apuntar a cadenas. Por ejemplo:

CHARACTER(LEN=100), DIMENSION(numStrings), TARGET :: stringArray 
TYPE(C_PTR), DIMENSION(numStrings) :: stringPtrs 

A continuación, establecemos nuestras cadenas en stringArray, recordando a null-terminará ellos, tales como:

DO ns = 1, numStrings 
    stringArray(ns) = "My String"//C_NULL_CHAR 
    stringPtrs(ns) = C_LOC(stringArray(ns)) 
END DO 

y pasar stringPtrs a la función C.

La función C tiene la interfaz:

void stringFunc(int *numStrings, char **stringArray) { 
    int i; 
    for(i=0;i<*numStrings;++i) { 
     printf("%s\n",stringArray[i]); 
    } 
} 
+0

¡Maravilloso, muchas gracias por la respuesta excepcionalmente rápida y útil! Para completar, el tipo en la interfaz es "type (c_ptr), dimension (numStrings)" – JoeZuntz

+0

Correcto, en nuestro código no proveemos una interfaz para la función C, la tratamos como 'externa', así que no tenía un ejemplo fácil del bloque de interfaz disponible. – tpg2114

+1

Esto no es estándar Fortran 2003 (ver sección 15.2.1) o 2008 (sección 15.3.2): ** Si el tipo es carácter, el parámetro de tipo de longitud es interoperable si y solo si su valor es uno. **. Y gfortran señala esto (usando el carácter * (len = ...) * con C_LOC) como un error. También hay un [debate] (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36759) sobre este tema en GCC bugzilla. –

Cuestiones relacionadas