使用C语言调用 liblapack.a 的使用方法及其原理探析

1, 使用方法

1.1 源代码

#include 
//#include 
extern void dgesv_(int*m, int* n, double*A, int*k, int*IP, double*B, int*j, int*info);

#define M 2
#define N 2

int main()
{
        int i, j, n=N, m=M;
        int info, IPIV[N];
        double A[M * N]= { 1,  2,  4,  2};
        double B[M*N] = {5, 4, 2.5, 2};

        dgesv_(&n, &n, A, &n, IPIV, B, &n, &info);

        for(j=0; j< 2*N; j++)
        {
                printf("%f\t", B[j]);
        }

        printf("\n");

        return 0;
}

1.2 构建

gcc hello_gesv.c -o hello_gesv  ../lapack-3.10.0/liblapack.a ../lapack-3.10.0/librefblas.a -lgfortran -lm

1.3 运行

使用C语言调用 liblapack.a 的使用方法及其原理探析_第1张图片

2.  为什么

2.1 问题1 函数名为何是这样的 dgesv_

命题: gfortran 在编译程序时,会将函数名字变成小写字母表示,而且会在末尾加一个下划线。

比如,如果fortran 的函数名是 HELLO_PR_FUNC,那么,在编译生成的elf 符号表中会变成 hello_pr_func_

验证如下:

fortran 程序源码

hello_fortran77_func.f:

        program main
        implicit none
        write(*,*) "Hello, fortran world!"

        call HELLO_PR_FUNC() ! call to invoke a subrutine
        end program main



        subroutine HELLO_PR_FUNC() ! define a subrutine
        implicit none
        write(*,*) "Hello, fortran subroutine!"

        end subroutine HELLO_PR_FUNC

构建Makefile

EXE := hello_gesv hello_fortran77_func

all: $(EXE)

INC      := 
LD_FLAGS := ../lapack-3.10.0/liblapack.a ../lapack-3.10.0/librefblas.a -lgfortran -lm

%: %.c
	gcc -g $^ -o $(@) $(LD_FLAGS)

%: %.f
	gfortran $^ -o $@

.PHONY: clean
clean:
	-rm -rf $(EXE)

构建:

make

nm:

$ nm hello_fortran77_func

效果图示:

使用C语言调用 liblapack.a 的使用方法及其原理探析_第2张图片

为什么函数名末尾会多出一个下划线呢?

这是 fortran 国际标准机构对fortran编译器提出了这样的要求,以减少与用户程序中函数名发生冲突的可能性。

是否可以取消这个下划线呢?是可以的 gfortran -fno-underscoring   xx.f -o xx

例如在上例子中 %: %.f 的规则中加入这样的选项后再重新编译,并 nm查看符号,会得到如下效果:

使用C语言调用 liblapack.a 的使用方法及其原理探析_第3张图片

 

2.2 问题2 有没有给fortran 程序的函数名在符号表中加前缀的方法

首先,在gfortran和fortran语言的国际标准中并没有这样的编译器选项;

但是,如果想给函数名字加前缀,那么比较好的方法是对 API 级别的函数做对应的包装函数,并export出来。如果是 shared library,则可以考虑 .map 

未完待续... ...

你可能感兴趣的:(c++,c语言,算法)