我动态链接到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”函数,我自己。
答案 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;
}