本文介绍了从ctypes访问通用块变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 我试图从Python脚本访问存储在Fortran 77公共块中的数据。问题是我不知道这些数据存储在哪里。 我正在开发的Python应用程序使用不同的库。这些库包含以下指令的函数: #include< tcsisc_common.inc> 常用的块包含: $ C INTEGER * 4 IDEBUG C C ....阵列尺寸 DIMENSION IDEBUG(10) C C .... COMMON BLOCK COMMON / TCSD / IDEBUG C 在Python部分(在我使用iPython的例子中),我加载了库: In [1]:import ctypes 在[2]中:_libtcsisc = /home/jfreixa/project/bin/libtcsisc.so 在[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(最近的最后一次调用)< ipython-input-6-ee5018286275> in< module>() ----> 1 idebug = ctypes.c_int.in_dll(_tcsisc,'IDEBUG_') ValueError:ld.so.1:python2.7:fatal:IDEBUG_:找不到符号 code> 任何想法都可以正确地获得变量? 解决方案根据此页面(特别是如何访问Fortran常见块从C)和一些 Q / A关于如何从Python访问C结构体,我们似乎可以像下面那样访问公共块(尽管这可能不是很便携,见下面): $ / mycom / n print *,fortsub> current / mycom / n =,n end 编译: $ gfortran -shared -fPIC -o mylib.so mylib.f90 test.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>修改/ mycom / n到777) mycom.n = 777 fortsub = mylib.fortsub_ fortsub() $ b 测试: $ python test .py python>修改/ mycom / n至777 fortsub> current / mycom / n = 777 这里请注意,公共块的名称(这里是 mycom )是小写字母和一个下划线(假设gfortran)。这个约定是依赖于编译器的,它可能更强大/更方便编写新的Fortran例程来设置/获取公共块中的值(特别是在 iso_c_binding 的帮助下)和调用那些来自Python的例程(如第一条评论中的@innoSPG所建议的那样)。 另一个包含不同类型和数组的例子可能看起来像这样: mylib.f90 $ p $ 子程序initcom() 隐式无整数n( 2),w !!假定与c_int real f(2)兼容! ...用c_float 双精度d(2)!! ... with c_double common / mycom / n,f,d,w $ b $ print *,(fort)initializing / mycom /n(:) = [1 ,2] f(:) = [3.0,4.0] d(:) = [5.0d0,6.0d0] w = 7 call printcom() end 子程序printcom()隐式无整数n(2),w 实数f(2)双精度d(2) common / mycom / n,f,d,w $ b print *,(fort)current / mycom / print *,n =,n print *,f =,f print *,d =,d print *,w =,w end test.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)modify / 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)初始化/ 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)modify / mycom / ... (fort)current / mycom / n = 10 20 f = 100.00000 200.00000 d = 0.10000000000000001 0.20000000000000001 w = 777 I am trying to access the data stored in a Fortran 77 common block from a Python script. The question is that I don't know where this data is stored.The Python application that I am developing makes use of different libraries. These libraries contain functions with the following directives:#include <tcsisc_common.inc>The common block contains:C INTEGER*4 IDEBUGCC.... ARRAY DIMENSIONS DIMENSION IDEBUG(10)CC.... COMMON BLOCK COMMON /TCSD/ IDEBUGCOn the Python part (on the example I have used iPython), I load the library: In [1]: import ctypesIn [2]: _libtcsisc= /home/jfreixa/project/bin/libtcsisc.soIn [3]: _tcsisc = ctypes.CDLL(_libtcsisc, ctypes.RTLD_GLOBAL)The problem is that I don't know how to get IDEBUG. I have tried the following, but I just get tcsd as a c_long initialized to 0.In [4]: tcsd = ctypes.c_int.in_dll(_tcsisc, "TCSD_")In [5]: tcsdOut[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 symbolAny idea to correctly get the variable? 解决方案 According to this page (particularly how to access Fortran common blocks from C) and some Q/A page about how to access C struct from Python, it seems that we could access common blocks as follows (though this may be not very portable, see below):mylib.f90subroutine fortsub() implicit none integer n common /mycom/ n print *, "fortsub> current /mycom/ n = ", nendcompile:$ gfortran -shared -fPIC -o mylib.so mylib.f90test.pyfrom __future__ import print_functionimport ctypesclass 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 = 777fortsub = mylib.fortsub_fortsub()Test: $ python test.py python> modifying /mycom/ n to 777 fortsub> current /mycom/ n = 777Here, please note that the name of the common block (here, mycom) is made lowercase and one underscore attached (by assuming gfortran). Because this convention is compiler-dependent, it may be more robust/portable to write new Fortran routines for setting/getting values in common blocks (particularly with the help of iso_c_binding) and call those routines from Python (as suggested by @innoSPG in the first comment).Another example including different types and arrays may look like this:mylib.f90subroutine 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()endsubroutine 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 = ", wendtest.pyfrom __future__ import print_functionimport ctypesN = 2class 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.1mycom.w = 777printcom = mylib.printcom_printcom()Test: $ 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 这篇关于从ctypes访问通用块变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 10-18 14:27