Un cocktail a base di Fortran, C++ e Lua

Mi hanno fatto una domanda nei commenti molto interessante: come posso sfruttare Lua con del codice Fortran? Bene, ho trovato una soluzione piuttosto semplice ed interessante per cui ho deciso di scriverci sopra un bel post.

Per prima cosa sappiate che non c’è un vero modo per collegare Lua a Fortran direttamente. Lua ha la sua libreria in C, pensata per il C e funziona per il C. Anche cercando in giro non ho trovato nulla che permetta il collegamento diretto. Tuttavia il Fortran e il C/C++ sono collegabili nativamente! Per questo motivo il procedimento si sintetizza in due punti

  • Collegare le funzioni Fortran alle funzioni C++
  • Collegare Lua alle funzioni C++

In questo modo il C++ assume il ruolo di collante fra Fortran e Lua e tutto funziona a meraviglia ma non solo: nonostante l’approccio a tre vie l’implementazione è formidabilmente trasparente e intuitiva!

Poiché sappiamo già come collegare Lua al C++ comincerò a far vedere come collegare Fortran a C++. Cominciamo con il codice C++ di esempio.

#include <iostream>

using namespace std;

extern "C" {
  void ffunction_(float *a, float *b);
}

int main()
{
    float a = 0;
    float b = 0;
   
    ffunction_(&a,&b);
   
    cout << a << " " << b << endl;
}

Il programma è stupido, lo so, ma rende l’idea. In pratica lasciamo che la funzione ffunction_ vada a modificare i valori delle due variabili a e b e poi stampiamo i nuovi valori.

Ma cosa fa ffunction_? Questa è la nostra funzione Fortran e nel codice C++ dobbiamo solo assicurarci che sia definita come extern. Il codice di questa funzione è semplice ed è salvato nel file ffunction.f.

      subroutine ffunction(a,b)
      a=3.0
      b=4.0
      end

Ora come compiliamo? Semplicissimo.

  • Prima compiliamo il codice C++ con g++ esempio.cpp -c ottenendo il file esempio.o
  • Poi compiliamo il codice fortran con gfortran ffunction.f -c ottenendo il file ffunction.o
  • Infine uniamo il tutto con g++ -o esempio esempio.o ffunction.o ottenendo l’eseguibile esempio

Niente di più semplice. In pratica, salvo definire le funzioni fortran come extern e l’uso di un compilatore diverso, l’integrazione fra fortran e C++ è praticamente trasparente!

A questo punto collegare Lua al Fortran è praticamente IDENTICO a collegare Lua al C++. Le nostre funzioni LuaGlue non faranno altro che chiamare funzioni Fortran come se stessero chiamando una funzione C++.

Supponiamo di voler chiamare una funzione Fortran che calcoli il fattoriale di un numero come nel caso di esempio di un articolo precedente:

LuaGlue _FortranFactorial(struct lua_State *pLuaState)
{
     double n;
     n = pLua->GetNumberArgument(1);
     
     /* Calcoliamo il fattoriale */
     int res = fortran_factorial_recursive_(n);
     
     /* Restituiamo il valore di ritorno */
     pLua->PushNumber(res);
     
     return 1;
}

Il codice è identico salvo che fortran_factorial_recursive_ questa volta non è una funzione C ma una funzione Fortran definita nel modo che abbiamo visto in precedenza.

E se siete abilissimi programmatori Fortran ma non sapete nulla di C++? Non credo sia un grosso problema, in questo approccio tutta la programmazione è eseguita in Fortran e Lua. Di C++ è necessario sapere proprio le basi e l’uso di LuaGrip per agganciare le funzioni a Lua, nulla più. Una piccola scocciatura e un piccolo sforzo iniziale in più per avere un integrazione Lua/Fortran praticamente perfetta.

5 comments on “Un cocktail a base di Fortran, C++ e Lua

  1. “E se siete abilissimi programmatori Fortran ma non sapete nulla di C++? ”

    Suggerisco di imparare il C++. Conosco entrambi, ed è un dato di fatto che fortran stia tentando ad ogni versione che passa di somigliare ad un linguaggio orientato agli oggetti, senza però riuscirci del tutto.
    Vi create le vostre classi in c++ per le cose che utilizzate di più (matrici, integratori, operatori vari) e siete apposto per la vita. Io avevo dei dubbi inizialmente, poi ho visto i sorgenti di OpenFOAM ed ho cambiato idea.

    • Effettivamente non credevo ci fossero ancora molte persone che utilizzassero il Fortran. Tuttavia con questo metodo “misto” il passaggio può risultare più soft. :D

      • Di fatto nel mondo delle simulazioni a fine scientifico fortran è un must, seguito a ruota da C, che però è meno noto. Il fatto è che è semplice da imparare, ha (aveva) pochi fronzoli ed i compilatori sono iperottimizzati per applicazioni numeriche. Tuttavia anche Numerical Receips (una bibbia del calcolo numerico) si è convertito al C++ cavalcando la sua lenta ma costante avanzata.

        La cosa divertente del Fortran è che tutti gli informatici sono convinti che non lo usi più nessuno mentre in realtà metà del codice che gira sui super-computer è Fortran XD

  2. Grazie, molto interessante!

    C’è un piccolo refuso: l’attributo o l’istruzione Fortran da usare per la funzione è “external” non “extern”. ;)

    • In c++ è extern ed è nel codice c++ che va dichiarata tale. :) Forse si capisce poco :O