从 python 中的共享 fortran 库调用函数

发布于 2024-11-03 21:23:03 字数 261 浏览 1 评论 0原文

我想在 Python 中调用 Fortran 共享库中的一些函数。我在网上找到了一些链接并阅读了它们,根据我发现的内容,我应该

libadd = cdll.LoadLibrary('./libbin.so') 

加载共享对象。但是,此共享对象包含来自另一个共享库的一些符号。我阅读了 cdll 的帮助,但是似乎不可能同时加载多个共享对象文件。我如何调用这个 Fortran 库中的函数(该库很可能是由英特尔 Fortran 编译器编译的)?

I would like to call some functions from a Fortran shared library in Python. I have found some links on the net and read them, and according what I found, I should do

libadd = cdll.LoadLibrary('./libbin.so') 

to load the shared object. However, this shared object includes some symbols from another shared library. I read the help of cdll however it does not seem possible to load several shared object files at the same time. How may I call functions from this Fortran library, which is most probably compiled by the Intel Fortran compiler?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

入怼 2024-11-10 21:23:03

您需要知道共享对象中函数的签名。您有源代码或一些解释函数名称和参数类型的参考吗?

例如,我有这个源代码(mult.f90):

integer function multiply(a, b)
    integer, intent(in) :: a, b
    multiply = a * b
end function multiply

..为了演示如何一次加载和使用多个共享对象,我还有(add.f90 strong>):

integer function addtwo(a, b)
    integer, intent(in) :: a, b
    addtwo = a + b
end function addtwo

编译,检查符号:

% gfortran-4.4 -shared -fPIC -g -o mult.so mult.f90
% gfortran-4.4 -shared -fPIC -g -o add.so add.f90
% nm -ao mult.so | grep multiply
mult.so:00000000000005cc T multiply_

注意共享库中的符号名称附加了下划线。由于我有源代码,我知道签名是 multiply_(int *a, int *b),因此很容易从 ctypes 调用该函数:

from ctypes import byref, cdll, c_int

mult = cdll.LoadLibrary('./mult.so')
add = cdll.LoadLibrary('./add.so')
a = c_int(2)
b = c_int(4)
print mult.multiply_(byref(a), byref(b))
print add.addtwo_(byref(a), byref(b))

输出:

8
6

You'll need to know the signatures of the functions in the shared object. Do you have the source code, or some reference which explains the function names and argument types?

For example, I have this source code (mult.f90):

integer function multiply(a, b)
    integer, intent(in) :: a, b
    multiply = a * b
end function multiply

.. and to demonstrate how you can load and use multiple shared objects at once, I also have (add.f90):

integer function addtwo(a, b)
    integer, intent(in) :: a, b
    addtwo = a + b
end function addtwo

Compile, examine symbols:

% gfortran-4.4 -shared -fPIC -g -o mult.so mult.f90
% gfortran-4.4 -shared -fPIC -g -o add.so add.f90
% nm -ao mult.so | grep multiply
mult.so:00000000000005cc T multiply_

Notice the symbol name in the shared object has an underscore appended. Since I have the source, I know that the signature is multiply_(int *a, int *b), so it is easy to invoke that function from ctypes:

from ctypes import byref, cdll, c_int

mult = cdll.LoadLibrary('./mult.so')
add = cdll.LoadLibrary('./add.so')
a = c_int(2)
b = c_int(4)
print mult.multiply_(byref(a), byref(b))
print add.addtwo_(byref(a), byref(b))

Output:

8
6
青巷忧颜 2024-11-10 21:23:03

我想在 @sameplebias 答案中添加一点,即可以使用 iso_c_binding 模块强制(任何)fortran 编译器生成正确的 C 签名。使用示例:

module fmesh_wrapper

use iso_c_binding, only: c_double, c_int
use fmesh, only: mesh_exp

implicit none

contains

subroutine c_mesh_exp(r_min, r_max, a, N, mesh) bind(c)
real(c_double), intent(in) :: r_min
real(c_double), intent(in) :: r_max
real(c_double), intent(in) :: a
integer(c_int), intent(in) :: N
real(c_double), intent(out) :: mesh(N)
call mesh_exp(r_min, r_max, a, N, mesh)
end subroutine

! wrap more functions here
! ...

end module

这将具有以下 C 签名:

void c_mesh_exp(double *r_min, double *r_max, double *a, int *N,
        double *mesh);

然后您可以像往常一样从 Python 调用它。这种方法的优点是它适用于所有平台(无需使用任何特殊的编译器选项)。

I would add to @sameplebias answer, that one can use the iso_c_binding module to force (any) fortran compiler to produce the correct C signature. Example of usage:

module fmesh_wrapper

use iso_c_binding, only: c_double, c_int
use fmesh, only: mesh_exp

implicit none

contains

subroutine c_mesh_exp(r_min, r_max, a, N, mesh) bind(c)
real(c_double), intent(in) :: r_min
real(c_double), intent(in) :: r_max
real(c_double), intent(in) :: a
integer(c_int), intent(in) :: N
real(c_double), intent(out) :: mesh(N)
call mesh_exp(r_min, r_max, a, N, mesh)
end subroutine

! wrap more functions here
! ...

end module

this will have the following C signature:

void c_mesh_exp(double *r_min, double *r_max, double *a, int *N,
        double *mesh);

and then you can call it from Python as usual. The advantage of this approach is that it works on all platforms (without using any special compiler options).

原来分手还会想你 2024-11-10 21:23:03

要使 f2py(来自 NumPy)正常工作,请借用@samplebias 中的 mult.f90add.f90 示例。从 shell 编译 Python 可导入共享库:

f2py -c -m mult mult.f90
f2py -c -m add add.f90

现在在 Python 中使用它们:

>>> import add
>>> import mult
>>> add.addtwo(4, 5)
9
>>> mult.multiply(4, 5)
20

For f2py (from NumPy) to work, borrow both the mult.f90 and add.f90 examples from @samplebias. From a shell, compile the Python importable shared libraries:

f2py -c -m mult mult.f90
f2py -c -m add add.f90

Now use them in Python:

>>> import add
>>> import mult
>>> add.addtwo(4, 5)
9
>>> mult.multiply(4, 5)
20
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文