gpt4 book ai didi

python - 从 ctypes 访问公共(public) block 变量

转载 作者:行者123 更新时间:2023-11-30 22:50:02 25 4
gpt4 key购买 nike

我正在尝试从 Python 脚本访问存储在 Fortran 77 公共(public) block 中的数据。问题是我不知道这些数据存储在哪里。我正在开发的 Python 应用程序使用不同的库。这些库包含具有以下指令的函数:

#include <tcsisc_common.inc>

公共(public) block 包含:

C
INTEGER*4 IDEBUG
C
C.... ARRAY DIMENSIONS
DIMENSION IDEBUG(10)
C
C.... COMMON BLOCK
COMMON /TCSD/ IDEBUG
C

在 Python 部分(在我使用 iPython 的示例中),我加载库:

In [1]: import ctypes
In [2]: _libtcsisc= /home/jfreixa/project/bin/libtcsisc.so
In [3]: _tcsisc = ctypes.CDLL(_libtcsisc, ctypes.RTLD_GLOBAL)

问题是我不知道如何获取IDEBUG。我尝试了以下方法,但我只是将 tcsd 作为 c_long 初始化为 0。

In [4]: tcsd = ctypes.c_int.in_dll(_tcsisc, "TCSD_")
In [5]: tcsd
Out[5]: c_long(0)
In [6]: idebug = ctypes.c_int.in_dll(_tcsisc, "IDEBUG_")
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-6-ee5018286275> in <module>()

----> 1 idebug = ctypes.c_int.in_dll(_tcsisc,'IDEBUG_')

ValueError: ld.so.1: python2.7: fatal: IDEBUG_: can't find symbol

有什么办法可以正确获取变量吗?

最佳答案

根据this page (特别是如何从 C 访问 Fortran 公共(public) block )和一些 Q/A page关于如何从Python访问C结构体,我们似乎可以按如下方式访问公共(public) block (尽管这可能不太可移植,见下文):

mylib.f90

subroutine fortsub()
implicit none
integer n
common /mycom/ n
print *, "fortsub> current /mycom/ n = ", n
end

编译:

$ gfortran -shared -fPIC -o mylib.so mylib.f90

测试.py

from __future__ import print_function
import ctypes

class Mycom( ctypes.Structure ):
_fields_ = [ ( "n", ctypes.c_int ) ]

mylib = ctypes.CDLL( "./mylib.so" )

mycom = Mycom.in_dll( mylib, "mycom_" )

print( " python> modifying /mycom/ n to 777" )

mycom.n = 777

fortsub = mylib.fortsub_
fortsub()

测试:

 $ python test.py 
python> modifying /mycom/ n to 777
fortsub> current /mycom/ n = 777

请注意,公共(public) block 的名称(此处为 mycom)为小写并附加一个下划线(假设为 gfortran)。由于此约定依赖于编译器,因此编写新的 Fortran 例程用于在公共(public) block 中设置/获取值(特别是在 iso_c_binding 的帮助下)并从 Python 调用这些例程可能会更健壮/可移植(正如@innoSPG 在第一条评论中所建议的那样)。

<小时/>

包含不同类型和数组的另一个示例可能如下所示:

mylib.f90

subroutine initcom()
implicit none
integer n( 2 ), w !! assumed to be compatible with c_int
real f( 2 ) !! ... with c_float
double precision d( 2 ) !! ... with c_double
common /mycom/ n, f, d, w

print *, "(fort) initializing /mycom/"
n(:) = [ 1, 2 ]
f(:) = [ 3.0, 4.0 ]
d(:) = [ 5.0d0, 6.0d0 ]
w = 7
call printcom()
end

subroutine printcom()
implicit none
integer n( 2 ), w
real f( 2 )
double precision d( 2 )
common /mycom/ n, f, d, w

print *, "(fort) current /mycom/"
print *, " n = ", n
print *, " f = ", f
print *, " d = ", d
print *, " w = ", w
end

测试.py

from __future__ import print_function
import ctypes

N = 2

class Mycom( ctypes.Structure ):
_fields_ = [ ( "x", ctypes.c_int * N ),
( "y", ctypes.c_float * N ),
( "z", ctypes.c_double * N ),
( "w", ctypes.c_int ) ]

mylib = ctypes.CDLL( "./mylib.so" )

mycom = Mycom.in_dll( mylib, "mycom_" )

initcom = mylib.initcom_
initcom()

print( " (python) current /mycom/" )
print( " x = ", mycom.x[:] )
print( " y = ", mycom.y[:] )
print( " z = ", mycom.z[:] )
print( " w = ", mycom.w )

print( " (python) modifying /mycom/ ..." )
for i in range( N ):
mycom.x[ i ] = (i + 1) * 10
mycom.y[ i ] = (i + 1) * 100
mycom.z[ i ] = (i + 1) * 0.1
mycom.w = 777

printcom = mylib.printcom_
printcom()

测试:

 $ python test.py

(fort) initializing /mycom/
(fort) current /mycom/
n = 1 2
f = 3.0000000 4.0000000
d = 5.0000000000000000 6.0000000000000000
w = 7
(python) current /mycom/
x = [1, 2]
y = [3.0, 4.0]
z = [5.0, 6.0]
w = 7
(python) modifying /mycom/ ...
(fort) current /mycom/
n = 10 20
f = 100.00000 200.00000
d = 0.10000000000000001 0.20000000000000001
w = 777

关于python - 从 ctypes 访问公共(public) block 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39533409/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com