首页 > 解决方案 > 如何告诉 f2py 模块在当前目录中查找共享对象依赖项

问题描述

system: lubuntu 18.04, running in VirtualBox

假设我有以下源目录(底部的代码):

/f2pyproject/
  - lib.f
  - prog.f
  - f2pyprog.f
  - test.py

prog.f是一个简单的 fortran 可执行文件,它将调用从lib.f.

为达到这个:

>>> gfortran -shared lib.f -o lib.so
>>> gfortran prog.f lib.so -o prog.exe -Wl,-rpath=.
>>> ./prog.exe
    hello world

-Wl,-rpath=.选项告诉 prog.exe 在当前目录中查找其链接的共享对象,这样我就不用担心$LD_LIBRARY_PATH

现在我想在 python 中调用这个相同的链接子例程,所以我用 f2py 调用编译 f2pyprog.f:

>>> python3 -m numpy.f2py -c f2pyprog.f lib.so -m prog

现在在这种情况下,prog.cpython-blah-blah.so是一个共享对象,而不是一个可执行文件,所以我不知道的是,如何调用这个工作流而不必担心 LD_LIBRARY_PATH 而是将共享对象与 f2py 编译库保持在同一目录中。

调用 test.py 失败:

>>> python3 test.py  (fails with ImportError, cannot open shared object file)

首先设置 LD_LIBRARY_PATH 成功:

>>> export LD_LIBRARY_PATH=`pwd`
>>> python3 test.py
    hello world

主要问题:

是否可以使用 -rpath 链接器选项之类的东西在当前目录中链接共享对象来构建这个(或任何)f2py 扩展,而不必担心$LD_LIBRARY_PATH环境变量?

资料来源:

lib.f:

  subroutine helloworld()
      print*, "hello world"
  return
  end subroutine

程序.f:

  program helloworldprog
    call helloworld()
  end program helloworldprog

f2pyprog.f:

  subroutine pyhelloworld()
    call helloworld()
  return
  end subroutine

测试.py

import os
from os import path
# has no effect, presumably because this needs to be set before python starts
os.environ['LD_LIBRARY_PATH'] = path.abspath(path.dirname(__file__))  

import prog
prog.pyhelloworld()

标签: pythonlinuxshared-librariesf2py

解决方案


  1. 设置环境变量export LDFLAGS=-Wl,-rpath=.
  2. 设置环境变量export NPY_DISTUTILS_APPEND_FLAGS=1
  3. 升级numpy1.16.0或更高

虽然您不能从 f2py 的命令行传递链接器标志,但它会读取LDFLAGS环境变量。但是,numpy 的默认行为是覆盖编译中使用的标志而不是附加它们,如果LDFLAGS. 版本中添加了支持numpy1.16.0,可以通过设置环境变量来选择性地附加这些链接器标志NPY_DISTUTILS_APPEND_FLAGS=1

>>> unset LD_LIBRARY_FLAGS   # just in case was set before
>>> export LDFLAGS=-Wl,-rpath=.
>>> export NPY_DISTUTILS_APPEND_FLAGS=1
>>> python3 -m numpy.f2py -c progpy.f lib.so -m prog
>>> python3 test.py
    hello world

推荐阅读