如何编译用于Python的Fortran库? (f2py可能不是一个选项) [英] How do I compile a Fortran library for use with Python? (f2py may not be an option)

查看:420
本文介绍了如何编译用于Python的Fortran库? (f2py可能不是一个选项)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图编译fortran90库(特别是这个),以便从python(3.4.0)中调用它。通常在这种情况下,我会为f2py编写一个封装器并将其称为一天,但库本身使用派生类型,这似乎是使f2py失败。完整的stderr 粘贴在这里,但相关行是

  getctype:没有在{'typename':'optim_type','typespec':'type'}中找到C类型,假定为void。 

另一个选项基于 numpy文档是使用ctypes,这也失败了



pre code $ Python $ 3.4.0(缺省值,2015年6月19日,14:20:21)
[GCC 4.8.2]在linux
上键入help ,版权,信用或许可证以获取更多信息。
>>> import numpy as np
>>> nb.ctypeslib.load_library('libLBFGS','/ home / kaplane / src / TOOLBOX_OPTIMIZATION_shared / lib')
Traceback(最近的最后一次调用):
文件stdin>,第1行,在< module>
文件/home/kaplane/.local/lib/python3.4/site-packages/numpy/ctypeslib.py,第123行,在load_library
返回ctypes.cdll [libpath]
在__getitem__
中返回文件/usr/lib/python3.4/ctypes/__init__.py,第426行,返回getattr(self,name)
文件/usr/lib/python3.4/ ctypes / __init__.py,第421行,在__getattr__
dll = self._dlltype(name)
文件/usr/lib/python3.4/ctypes/__init__.py,第351行,in __init__
self._handle = _dlopen(self._name,mode)
OSError:/home/kaplane/src/TOOLBOX_OPTIMIZATION_shared/lib/libLBFGS.so:invalid ELF header

我无法弄清楚什么是ELF标题无效。来自 $ readelf -h 的输出与共享库的效果是一样的(除了数字,大小以及程序和节头的位置)。



我如何编译库



在我的本地机器上编译我使用gfortran而不是ifort,并且设置了编译器标志作为

  OPTF = -O3 -shared -fPIC 
OPTC = -O3 -shared -fPIC
OPTL = -O3 -shared -fPIC
AR = ar
ARFUNCT = cruvs

Makefile.inc 文件中。我也运行脚本

  find ./ -nameMakefile| xargs sed -i -e's / lib \([AZ] * \)\.a / lib\1.so / g'

,以便将这些库标记为 .so ,而不是 .a 。这似乎并不影响示例程序的运行。



我想知道的是什么



我认为最好的选择是弄清楚如何编译这个库,这样我就不会收到无效的ELF错误。如果没有,我需要弄清楚如何编译带有派生类型的Fortran模块,但是我所做的搜索并不是很有前途。

解决方案 div>

f2py是为Fortran77代码编写的,因此不支持Fortran90 +的大部分功能,例如派生类型,可分配数组等。



我自己的解决方法包括在我想使用的子例程周围编写一个Fortran包装程序。在这个包装程序中,我将所有可分配数组(因为这是唯一使用的不支持的功能)复制到固定大小的数组(f2py似乎还有一个未公开的最大数组大小:/)。这些固定大小的数组以及原始数组的大小随后被用作fortran包装程序的输出。



另外,我为所生成的f2py编写了一个python包装程序它读取这些固定大小的数组(包括大小信息),并只返回实际数据(从固定大小的数组中删除所有未使用的行/列等)。

这种方法是唯一可行的,因为我对源文件和预期数据拥有完全的控制权和知识。我会不是推荐它,如果你的工作不能被你的工作人员使用。






<作为一种选择,你应该看看Cython。这提供了一种在Fortran和Python例程之间使用 iso_c_binding [2] 。有关最低工作示例,请参阅此处。在这个问题的第一条评论中可以找到一个很好的讨论(以供参考)。



我使用了上述解决方法,因为那时我无法恢复工作。但是我刚刚提到的那些重要的讲座和教程都已经添加了,这会让它变得更容易。


I'm trying to compile a fortran90 library (specifically this one) in order to call it from python (3.4.0). Generally in this case I would write a wrapper for f2py and call it a day, but the library itself makes use of derived types, which seems to be making f2py fail. The full stderr is pasted here, but the relevent line is

getctype: No C-type found in "{'typename': 'optim_type', 'typespec': 'type'}", assuming void.

The other option, based on the numpy documentation is to use ctypes, which also fails

Python 3.4.0 (default, Jun 19 2015, 14:20:21) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.ctypeslib.load_library('libLBFGS', '/home/kaplane/src/TOOLBOX_OPTIMIZATION_shared/lib')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/kaplane/.local/lib/python3.4/site-packages/numpy/ctypeslib.py", line 123, in load_library
    return ctypes.cdll[libpath]
  File "/usr/lib/python3.4/ctypes/__init__.py", line 426, in __getitem__
    return getattr(self, name)
  File "/usr/lib/python3.4/ctypes/__init__.py", line 421, in __getattr__
    dll = self._dlltype(name)
  File "/usr/lib/python3.4/ctypes/__init__.py", line 351, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: /home/kaplane/src/TOOLBOX_OPTIMIZATION_shared/lib/libLBFGS.so: invalid ELF header

What I can't figure out is exactly what is invalid about the ELF header. The output from $ readelf -h is the same (excepting number, size, and locations of program and section headers) as for a shared library that works.

How I'm compiling the library

Compiling on my local machine I use gfortran instead of ifort, and have the compiler flags set as

OPTF =  -O3 -shared -fPIC
OPTC =  -O3 -shared -fPIC
OPTL =  -O3 -shared -fPIC
AR= ar 
ARFUNCT= cruvs

in the Makefile.inc file. I also run a script

find ./ -name "Makefile" | xargs sed -i -e 's/lib\([A-Z]*\)\.a/lib\1.so/g'

so that the libraries are labeled as .so instead of .a. This doesn't seem to affect the operation of the examples programs.

What I'd like to know

I think the best option is to figure out how to compile the library such that I don't get that invalid ELF error. Failing that I'd need to figure out how to compile Fortran modules with derived types, but the searching I've done is less than promising.

解决方案

f2py is writen for Fortran77 Code and therefore does not support most of the features of Fortran90+, such as derived types, allocatable arrays, etc.

My own workaround incorporated writing a Fortran wrapper routine arround the subroutines I wanted to use. In this wrapper routine I copied all allocatable arrays (because that was the only unsupported feature that was used) to fixed size arrays (f2py also seems to have an undocumented maximum arrays size :/ ). These fixed size arrays, along with the size of the original arrays was then used as output of the fortran wrapper routine.

Additionally I wrote a python wrapper routine for the generated f2py library that read those fixed size arrays (read LARGE), including the size information and only returned the actual data (removing all the unused rows/ columns, etc. from the fixed size array).

This approach was only possible, because I had full control and knowledge of the source files and expected data. I would not recommend it if your work might ot be used by somebody outside of your reach.


As an alternative you should have a look at Cython. This provides an almost native way to exchange data between Fortran and Python routines using iso_c_binding [2]. For a minimum working example look here. A great talk about that can also be found in the 1st comment of this question (for reference).

I used the above workaround because I couldn't get it to work back then. But the great talks and tutorials I just mentioned have been added since, that should make it a whole lot easier.

这篇关于如何编译用于Python的Fortran库? (f2py可能不是一个选项)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆