4

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

为清楚起见,我想要一个能够接受字符串的函数,将其解释为 fortran 子例程名称,并针对给定的编译器进行适当的处​​理。在伪 C++ 中,:

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

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

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

4

2 回答 2

4

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

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

另一种方法是您知道如何完成修改,并相应地实现 FortranMangle 例程。没有为此做任何预先准备,因为修饰是编译器特定的,并且规范中对此没有任何内容。

于 2011-08-24T12:42:15.820 回答
2

这是一个快速而肮脏的 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;
}
于 2011-08-24T13:54:54.370 回答