4
votes

I am dynamically linking to a fortran static object and need to be able (at run time) to take the name of the fortran function (which is a C++ string) and name mangle it appropriately for the compiler. Is there any pre-built function that would serve this purpose? In the statically linked case I am using autoconf's FC_FUNC.

For clarity, I want a function that would be able to take a string, interpret it as a fortran subroutine name and mangle it appropriately for the given compiler. In psuedo-C++,:

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

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

I do not know all of the used name mangling schemes to write this mysterious "FortranMangle" function, myself.

2
What are you trying to accomplish with this (never done anything alike so I'm curious? - Rook
@Rook probably because he wants to access fortran routines in runtime with dlopen, but since the symbol changes according to the fortran compiler, he does not know what to pass to dlsym - Stefano Borini
@Stefano - Ah, ok. But, how many compilers is he using that he cannot do this by hand? - Rook
I can do this by hand. However, if something exists that is far more robust than what I write then I'd rather use it. What's more, I'm not in a development environment where I've got access to a large array of compilers. - V.S.

2 Answers

4
votes

I assume you want to access fortran routines in runtime from C with dlopen. Since the symbol changes according to the fortran compiler, you don't know what to pass to dlsym in order to get the symbol.

one possible solution is to specify the fortran routine you want to call with BIND(C). This removes name mangling and uses C-style symbol name, that is, one-to-one mapping.

The alternative is that you know how the mangling is done, and implement the FortranMangle routine accordingly. There's nothing premade for that, because mangling is compiler specific and there's nothing in the spec about this.

2
votes

Here's a quick and dirty C solution that abuses the existing macros to extract the mangling rules and print the mangled result. Most of this gets elided by the optimizer, so only the relevant cases exist. You should be able to adapt this to your 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;
}