Compiler agnostic fortran name mangling function
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 functi开发者_如何学JAVAon 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.
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.
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;
}
精彩评论