El archivo prog.c es el mismo de la carpeta 2_ProgramaC-SubrutinasC. El archivo subs.f es el mismo de la carpeta 1_ProgramaFortran-SubrutinasFortran. El archivo enlace.c permite enlazar el programa C con la subrutina Fortran. Nótese que: - En Fortran la transferencia de argumentos se realiza por referencia (excepto en el caso de los argumentos de tipo character). - En C la transferencia de argumentos se realiza normalmente por valor salvo que se indique lo contrario (con el prefijo &), en cuyo caso se realiza por referencia. Se exceptúan los vectores, que se transfieren por referencia (ya que v, v[] y &v[0] son equivalentes). - Los compiladores Fortran no distinguen las mayúsculas de las minúsculas (salvo que contengan una opción de compilación que cambie esta forma de proceder). En particular, el compilador GFortran pasa a minúsculas los nombres de las subrutinas y les añade un guion bajo (carácter "_") al final. En otros compiladores el criterio puede ser diferente (puede que el nombre se pase a mayúsculas o que se añadan o no otros caracteres). - Los compiladores C distinguen las mayúsculas de las minúsculas. El compilador GCC conserva las mayúsculas y minúsculas en los nombres de las funciones. Por ello: - En el programa C las llamadas BubbleSort(n, v); HeapSort(n, v); QuickSort(n, v); se compilan de forma equivalente a BubbleSort(n, &v[0]); HeapSort(n, &v[0]); QuickSort(n, &v[0]); - Las subrutinas Fortran Subroutine BubbleSort(n,v) implicit real*8 (a-h,o-z) dimension v(n) ... end Subroutine HeapSort(n,v) implicit real*8 (a-h,o-z) dimension v(n) ... end Subroutine QuickSort(n,v) implicit real*8 (a-h,o-z) dimension v(n) ... end se compilan de forma equivalente a las funciones C void bubblesort_(int *n , double *v) { ... } void heapsort_(int *n , double *v) { ... } void quicksort_(int *n , double *v) { ... } - Por ello, el programa C no se puede enlazar correctamente con las subrutinas Fortran, ya que -- El nombre de la función a la que se llama no coincide con el de la función que recibe. -- El primer argumento se transfiere por valor y se recibe por referencia. Soluciones: 1) Modificar el programa C, de forma que las llamadas se escriban como bubblesort_(&n, v); heapsort_(&n, v); quicksort_(&n, v); Puede ser necesario reprogramar la subrutina Fortran si en su interior se modifica el valor de n, ya que de lo contrario se modificará el valor de n en el programa principal. 2) Añadir las funciones C auxiliares void BubbleSort(int n , double *v) { void bubblesort_(int *, double *); bubblesort_(&n, v); } void HeapSort(int n , double *v) { void heapsort_(int *, double *); heapsort_(&n, v); } void QuickSort(int n , double *v) { void quicksort_(int *, double *); quicksort_(&n, v); } que actuarán como enlace entre el programa C y las subrutinas Fortran. En esencia, estas funciones auxiliares reciben el primer argumento (n) por valor y el segundo (v) por referencia y pasan los dos argumentos (n, v) por referencia a las subrutinas Fortran. No será necesario reprogramar las subrutinas Fortran aunque en su interior se modifique el valor de n, ya que los valores de n que se reciben serán los de las funciones de enlace, (que son copias de los valores de n en el programa principal). __________ OBSERVACIÓN:En la subrutina Fortran QuickSort(n,v) se utiliza la instrucción write(,) de Fortran. Para que esta instrucción pueda funcionar debe tener acceso al contenido de la librería de gfortran. Pero el programa ejecutable no se monta con gfortran sino con gcc, que no tiene acceso automático al contenido de esta librería. Para que gcc pueda acceder al contenido de esta librería es preciso linkar con la opción -lgfortran.