思路
利用f2c,转换lapack的fortran源文件,获得函数的C头文件声明。
转换代码
通过遍历SRC文件夹中的文件来实现。这样的话会把某些没有在工程中编译的函数写进来。
可以通过搜索工程文件vfproj,来获得真正编译进来的函数。
结合昨天def文件的生成,把C头文件声明也生成了
但是f2c不支持fortran的一些新特性,因此一些函数转换不了。将这些函数放在 _buildCHeader.log文件中了。如果用到这些函数,则需要自己转换成C头文件了。
import re
import os
import codecs
import subprocess
fcexefile='C:\\f2c.exe'
projs=('C:\\lapack-3.8.0\\vc2015_build\\SRC\\lapack.vfproj',
'C:\\lapack-3.8.0\\vc2015_build\\BLAS\\SRC\\blas.vfproj')
exclude='DSECND_EXT_ETIME SECOND_EXT_ETIME DSECND_EXT_ETIME SECOND_EXT_ETIME'
for proj in projs:
projpath=proj[:proj.rfind('\\')]
libname=proj[proj.rfind('\\')+1:proj.rfind('.')]
deffile=open(projpath+"\\"+libname+".def",'wt')
deffile.write("LIBRARY "+libname+"\nEXPORTS\n")
ddeffile=open(projpath+"\\"+libname+"d.def",'wt')
ddeffile.write("LIBRARY "+libname+"d\nEXPORTS\n")
fchead=open(projpath+"\\"+libname+'.h','wt')
fchead.write('#pragma once\n\n#ifdef __cplusplus\nextern "C" {\n#endif\n\n#include "f2c.h"\n\n')
ferrlog=open(projpath+"\\"+libname+'_buildCHeader.log','wt')
f=open(proj)
for line in f.readlines():
l=line.strip();
m=re.match(r'^<File RelativePath=\"',l)#匹配前面“<File RelativePath="”
if(m is not None):
m=re.search(r'\.f\"[\s]*[/]?>',l) #后面的“.f"\>”或“.f">”
if(m is not None):
path=l[20:l.find(m.group())]# .f 文件路径(不带后缀 .f)
name=path[path.rfind('\\')+1:] # .f 文件名
path=path+'.f' # .f 文件路径(加上后缀)
if(exclude.find(name.upper())==-1):
deffile.write("\t"+name.upper()+"\n")
deffile.write("\t"+name+"_="+name.upper()+"\n") #别名
ddeffile.write("\t"+name.upper()+"\n")
ddeffile.write("\t"+name+"_="+name.upper()+"\n") #别名
###写入C头文件申明
if(subprocess.run(fcexefile + ' ' + path).returncode==0): #f2c 转成 C文件,returncode==0表示成功
fcfile=codecs.open(path[:-2]+'.c','r','utf-8') #打开 C文件
cline=fcfile.readline() #读取C文件的一行
funcname=name.lower()+'_' #函数名
while cline!='': #如果文件没有结束
if cline.find(funcname+'(')>=0: #这一行是否有函数名+括号,如果有则找到了函数声明这一行了!
li=cline.rstrip() #去掉空格
fchead.write(li) #将这一行写到头文件中
while li!='' and li[-1]!=')':#如果这一行结尾不是右括弧,则下一行还是函数声明
li=fcfile.readline().rstrip() #读取下一行,并去掉空格
fchead.write(li) #写入这一行
fchead.write(';\n') #最后写入结束符
break; #由于函数声明已经找到,后续的文件内容不必在读了!
cline=fcfile.readline(); #如果这一行不是的话,继续找
fcfile.close() #关闭C文件
else:
ferrlog.write('Convert to C file error: ' + path+'\n')
os.remove(path[:-2]+'.c')#删除C文件(不成功,也会生成一个长度为0的文件
ferrlog.close()
f.close()
deffile.close()
ddeffile.close()