4 votes

Fonction de maniement des noms fortran agnostique pour le compilateur

Je fais un lien dynamique vers un objet statique fortran et je dois être capable (au moment de l'exécution) de prendre le nom de la fonction fortran (qui est une chaîne C++) et de le modifier de manière appropriée pour le compilateur. Existe-t-il une fonction préconstruite qui pourrait servir à cet effet ? Dans le cas d'une liaison statique, j'utilise FC_FUNC d'autoconf.

Pour plus de clarté, je veux une fonction capable de prendre une chaîne de caractères, de l'interpréter comme un nom de sous-routine fortran et de la modifier de manière appropriée pour le compilateur donné. En psuedo-C++, :

std::string subroutine = "FORTRANSUBROUTINE";
std::string symbol     = FortranMangle(subroutine);

std::cout << symbol << endl; // Would output something like "fortransubroutine_"

Je ne connais pas moi-même tous les schémas de manipulation de noms utilisés pour écrire cette mystérieuse fonction "FortranMangle".

4voto

Stefano Borini Points 36904

Je suppose que vous voulez accéder à des routines fortran en cours d'exécution à partir de C avec dlopen. Comme le symbole change en fonction du compilateur fortran, vous ne savez pas quoi passer à dlsym pour obtenir le symbole.

une solution possible est de spécifier la routine fortran que vous voulez appeler avec BIND(C) . Cela permet de supprimer la confusion des noms et d'utiliser le nom des symboles à la manière du C, c'est-à-dire une correspondance biunivoque.

L'autre solution consiste à savoir comment le découpage est effectué et à implémenter la routine FortranMangle en conséquence. Il n'y a rien de prévu à cet effet, car la gestion est spécifique au compilateur et il n'y a rien dans les spécifications à ce sujet.

2voto

Hasturkun Points 18653

Voici une solution rapide et sale en C qui abuse des macros existantes pour extraire les règles d'écrasement et imprimer le résultat écrêté. La plupart de ces opérations sont éludées par l'optimiseur, de sorte que seuls les cas pertinents existent. Vous devriez être capable d'adapter cette solution à votre code.

#include <stdio.h>
#include <string.h>

/* The autoconf macros, predefined here for uppercase, underscore,
 * extra underscore */
#define FC_FUNC(name, NAME) NAME ## _
#define FC_FUNC_(name, NAME) NAME ## __

#define STR(arg) STR1(arg)
#define STR1(arg) #arg

int main(int argc, char **argv)
{
    const char normal[] = STR(FC_FUNC(l, U));
    const char w_uscore[] = STR(FC_FUNC_(l, U));
    char ucase, uscore, extra_uscore;
    char buf[256];
    int i;

    ucase = normal[0] == 'l' ? 0 : 1;
    if (sizeof(normal) > sizeof("l"))
        uscore = 1;
    else
        uscore = 0;

    if (sizeof(w_uscore) > sizeof(normal))
        extra_uscore = 1;
    else
        extra_uscore = 0;

    printf("upper: %d uscore: %d extra :%d\n", ucase, uscore, extra_uscore);

    if (argc < 2)
        return -1;

    /* Copy string, converting case */
    for (i=0; i < strlen(argv[1]); i++)
    {
        buf[i] = ucase ? toupper(argv[1][i]) : tolower(argv[1][i]);
    }

    if (uscore)
        buf[i++] = '_';

    if (extra_uscore && strchr(argv[1], '_'))
    {
        buf[i++] = '_';
    }

    buf[i] = '\0';

    printf("old: %s - new %s\n", argv[1], buf);

    return 0;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X