编译器不可知的fortran名称修改功能

时间:2011-08-24 12:28:29

标签: c++ fortran name-mangling

我动态链接到fortran静态对象,并且需要能够(在运行时)获取fortran函数的名称(这是一个C ++字符串),并为编译器命名。是否有任何预先建立的功能可以达到此目的?在静态链接的情况下,我正在使用autoconf的FC_FUNC。

为了清楚起见,我想要一个能够获取字符串的函数,将其解释为fortran子例程名称并为给定的编译器适当地修改它。在psuedo-C ++中:

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

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

我不知道所有使用过的名称修改方案来编写这个神秘的“FortranMangle”函数,我自己。

2 个答案:

答案 0 :(得分:4)

我假设您想要在运行时使用dlopen从C访问fortran例程。由于符号根据fortran编译器而变化,因此您不知道要传递给dlsym以获取符号。

一种可能的解决方案是使用BIND(C)指定要调用的fortran例程。这将删除名称修改并使用C样式的符号名称,即一对一映射。

另一种方法是你知道如何完成修改,并相应地实现FortranMangle例程。没有预先制作,因为镶嵌是特定于编译器的,并且规范中没有任何内容。

答案 1 :(得分:1)

这是一个快速而肮脏的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;
}