Независимая от компилятора функция искажения имени Фортрана - PullRequest
3 голосов
/ 24 августа 2011

Я динамически связываюсь со статическим объектом fortran, и мне нужно иметь возможность (во время выполнения) взять имя функции fortran (которая является строкой C ++) и присвоить ей имя, соответствующее компилятору. Есть ли какая-нибудь заранее созданная функция, которая бы служила этой цели? В статически связанном случае я использую FC_FUNC для autoconf.

Для ясности я хочу функцию, которая могла бы взять строку, интерпретировать ее как имя подпрограммы на фортране и соответствующим образом изменить ее для данного компилятора. В псевдо-C ++:

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

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

Я не знаю всех используемых схем искажения имен, чтобы написать эту таинственную функцию "FortranMangle", сам.

Ответы [ 2 ]

4 голосов
/ 24 августа 2011

Я предполагаю, что вы хотите получить доступ к процедурам на фортране во время выполнения из C с помощью dlopen. Так как символ изменяется в соответствии с компилятором фортрана, вы не знаете, что передать dlsym, чтобы получить символ.

одним из возможных решений является указание фортрановой процедуры, которую вы хотите вызвать с помощью BIND (C) . Это удаляет искажение имени и использует имя символа в стиле C, то есть сопоставление «один к одному».

Альтернатива состоит в том, что вы знаете, как выполняется искажение, и соответственно реализуете процедуру FortranMangle. Для этого ничего не готово, потому что искажение зависит от компилятора, и в спецификации нет ничего по этому поводу.

1 голос
/ 24 августа 2011

Вот быстрое и грязное решение C, которое использует существующие макросы для извлечения правил искажения и печати искаженного результата.Большая часть этого исключается оптимизатором, поэтому существуют только соответствующие случаи.Вы должны быть в состоянии приспособить это к вашему коду.

#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;
}
...