Python ctypes将结构字段中的指针传递给Fortran派生类型

2024-09-28 17:04:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我想创建一个可变大小的数组传递给Fortran DLL并获得结果(通过引用),这样我就可以直接获得值。在

在Fortran代码中,我使用可分配变量,我认为它就像指向分配地址的指针。在

我可以做到以下几点,但我不知道如何在结构上做到:

test = POINTER(c_double)()

sim.structtest(input, byref(test))

Fortran中test的定义是

^{pr2}$

原代码:

Python代码(结构测试.py)公司名称:

from ctypes import *
import sys
import os


sim = cdll.LoadLibrary("struct.so")

class Input( Structure ):
    _fields_ = [( "a", c_double * 1 ),
                ( "b", c_double )]

class Output( Structure ):
    _fields_ = [( "a", c_double ),
                ( "b", POINTER(c_double) )] #-> don't know how to do

def main(): 
    input = Input()
    output = Output()
    input.a[0] = 1   
    input.b = 2

    sim.structtest(input, byref(output))

Fortran代码(struct.f90):

subroutine structtest(input, output) bind(c, name='structtest')

    USE ISO_C_BINDING
    IMPLICIT NONE

    !define input structure
    TYPE T_INPUT
        !real*8, allocatable :: a(:)
        real(kind=8) :: a(1)
        real(kind=8) :: b
    END TYPE T_INPUT

    !define output structure
    TYPE T_OUTPUT
        real(kind=8) :: a
        real(kind=8), allocatable, dimension (:) :: b
    END TYPE T_OUTPUT


    !define a variable "input" with structure "INPUT"
    TYPE (T_INPUT), value :: input

    TYPE (T_OUTPUT) :: output


    allocate(output%d(1))


    output%b(1) = 5
    PRINT *, output%d(1)

我将Fortran编译为DLL,如下所示:

ifort -shared -fPIC -static-intel -o struct.so struct.f90

我将Python执行为:

python structtest.py

我得到的结果是:

*** Error in `python': free(): corrupted unsorted chunks: 0x0000000001f7af00 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7fc9027f57e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x8037a)[0x7fc9027fe37a]
/lib/x86_64-linux-gnu/libc.so.6(cfree+0x4c)[0x7fc90280253c]
/lib/x86_64-linux-gnu/libc.so.6(__open_catalog+0xe8)[0x7fc9027b2008]
/lib/x86_64-linux-gnu/libc.so.6(catopen+0x4c)[0x7fc9027b1c2c]
/home/mingster/simGeo.docker/simgeo/lib/struct.so(for__issue_diagnostic+0x11e)[0x7fc90147a77e]
/home/mingster/simGeo.docker/simgeo/lib/struct.so(for_allocate+0x303)[0x7fc90146b9a3]
/home/mingster/simGeo.docker/simgeo/lib/struct.so(structtest+0xae)[0x7fc90146b16e]
/usr/lib/x86_64-linux-gnu/libffi.so.6(ffi_call_unix64+0x4c)[0x7fc901757e40]
/usr/lib/x86_64-linux-gnu/libffi.so.6(ffi_call+0x2eb)[0x7fc9017578ab]
/usr/lib/python2.7/lib-dynload/_ctypes.x86_64-linux-gnu.so(_ctypes_callproc+0x48f)[0x7fc9019673df]
/usr/lib/python2.7/lib-dynload/_ctypes.x86_64-linux-gnu.so(+0x11d82)[0x7fc90196bd82]
python(PyObject_Call+0x43)[0x4b0c93]
python(PyEval_EvalFrameEx+0x602f)[0x4c9f9f]
python(PyEval_EvalFrameEx+0x5e0f)[0x4c9d7f]
python(PyEval_EvalCodeEx+0x255)[0x4c2705]
python(PyEval_EvalCode+0x19)[0x4c24a9]
python[0x4f19ef]
python(PyRun_FileExFlags+0x82)[0x4ec372]
python(PyRun_SimpleFileExFlags+0x191)[0x4eaaf1]
python(Py_Main+0x6c8)[0x49e208]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fc90279e830]
python(_start+0x29)[0x49da59]
======= Memory map: ========
00400000-006e9000 r-xp 00000000 08:01 525090                             /usr/bin/python2.7
008e8000-008ea000 r--p 002e8000 08:01 525090                             /usr/bin/python2.7
008ea000-00961000 rw-p 002ea000 08:01 525090                             /usr/bin/python2.7
00961000-00984000 rw-p 00000000 00:00 0
01f10000-01ff6000 rw-p 00000000 00:00 0                                  [heap]
7fc8fc000000-7fc8fc021000 rw-p 00000000 00:00 0
7fc8fc021000-7fc900000000 ---p 00000000 00:00 0
7fc901246000-7fc90125c000 r-xp 00000000 08:01 38797837                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7fc90125c000-7fc90145b000 ---p 00016000 08:01 38797837                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7fc90145b000-7fc90145c000 rw-p 00015000 08:01 38797837                   /lib/x86_64-linux-gnu/libgcc_s.so.1
7fc90145c000-7fc901504000 r-xp 00000000 08:01 51643749                   /home/mingster/simGeo.docker/simgeo/lib/struct.so
7fc901504000-7fc901704000 ---p 000a8000 08:01 51643749                   /home/mingster/simGeo.docker/simgeo/lib/struct.so
7fc901704000-7fc90170a000 rw-p 000a8000 08:01 51643749                   /home/mingster/simGeo.docker/simgeo/lib/struct.so
7fc90170a000-7fc901752000 rw-p 00000000 00:00 0
7fc901752000-7fc901759000 r-xp 00000000 08:01 526635                     /usr/lib/x86_64-linux-gnu/libffi.so.6.0.4
7fc901759000-7fc901958000 ---p 00007000 08:01 526635                     /usr/lib/x86_64-linux-gnu/libffi.so.6.0.4
7fc901958000-7fc901959000 r--p 00006000 08:01 526635                     /usr/lib/x86_64-linux-gnu/libffi.so.6.0.4
7fc901959000-7fc90195a000 rw-p 00007000 08:01 526635                     /usr/lib/x86_64-linux-gnu/libffi.so.6.0.4
7fc90195a000-7fc901978000 r-xp 00000000 08:01 30543353                   /usr/lib/python2.7/lib-dynload/_ctypes.x86_64-linux-gnu.so
7fc901978000-7fc901b77000 ---p 0001e000 08:01 30543353                   /usr/lib/python2.7/lib-dynload/_ctypes.x86_64-linux-gnu.so
7fc901b77000-7fc901b78000 r--p 0001d000 08:01 30543353                   /usr/lib/python2.7/lib-dynload/_ctypes.x86_64-linux-gnu.so
7fc901b78000-7fc901b7c000 rw-p 0001e000 08:01 30543353                   /usr/lib/python2.7/lib-dynload/_ctypes.x86_64-linux-gnu.so
7fc901b7c000-7fc901e54000 r--p 00000000 08:01 529135                     /usr/lib/locale/locale-archive
7fc901e54000-7fc901f5c000 r-xp 00000000 08:01 38797852                   /lib/x86_64-linux-gnu/libm-2.23.so
7fc901f5c000-7fc90215b000 ---p 00108000 08:01 38797852                   /lib/x86_64-linux-gnu/libm-2.23.so
7fc90215b000-7fc90215c000 r--p 00107000 08:01 38797852                   /lib/x86_64-linux-gnu/libm-2.23.so
7fc90215c000-7fc90215d000 rw-p 00108000 08:01 38797852                   /lib/x86_64-linux-gnu/libm-2.23.so
7fc90215d000-7fc902176000 r-xp 00000000 08:01 38797934                   /lib/x86_64-linux-gnu/libz.so.1.2.8
7fc902176000-7fc902375000 ---p 00019000 08:01 38797934                   /lib/x86_64-linux-gnu/libz.so.1.2.8
7fc902375000-7fc902376000 r--p 00018000 08:01 38797934                   /lib/x86_64-linux-gnu/libz.so.1.2.8
7fc902376000-7fc902377000 rw-p 00019000 08:01 38797934                   /lib/x86_64-linux-gnu/libz.so.1.2.8
7fc902377000-7fc902379000 r-xp 00000000 08:01 38797927                   /lib/x86_64-linux-gnu/libutil-2.23.so
7fc902379000-7fc902578000 ---p 00002000 08:01 38797927                   /lib/x86_64-linux-gnu/libutil-2.23.so
7fc902578000-7fc902579000 r--p 00001000 08:01 38797927                   /lib/x86_64-linux-gnu/libutil-2.23.so
7fc902579000-7fc90257a000 rw-p 00002000 08:01 38797927                   /lib/x86_64-linux-gnu/libutil-2.23.so
7fc90257a000-7fc90257d000 r-xp 00000000 08:01 38797825                   /lib/x86_64-linux-gnu/libdl-2.23.so
7fc90257d000-7fc90277c000 ---p 00003000 08:01 38797825                   /lib/x86_64-linux-gnu/libdl-2.23.so
7fc90277c000-7fc90277d000 r--p 00002000 08:01 38797825                   /lib/x86_64-linux-gnu/libdl-2.23.so
7fc90277d000-7fc90277e000 rw-p 00003000 08:01 38797825                   /lib/x86_64-linux-gnu/libdl-2.23.so
7fc90277e000-7fc90293e000 r-xp 00000000 08:01 38797811                   /lib/x86_64-linux-gnu/libc-2.23.so
7fc90293e000-7fc902b3e000 ---p 001c0000 08:01 38797811                   /lib/x86_64-linux-gnu/libc-2.23.so
7fc902b3e000-7fc902b42000 r--p 001c0000 08:01 38797811                   /lib/x86_64-linux-gnu/libc-2.23.so
7fc902b42000-7fc902b44000 rw-p 001c4000 08:01 38797811                   /lib/x86_64-linux-gnu/libc-2.23.so
7fc902b44000-7fc902b48000 rw-p 00000000 00:00 0
7fc902b48000-7fc902b60000 r-xp 00000000 08:01 38797898                   /lib/x86_64-linux-gnu/libpthread-2.23.so
7fc902b60000-7fc902d5f000 ---p 00018000 08:01 38797898                   /lib/x86_64-linux-gnu/libpthread-2.23.so
7fc902d5f000-7fc902d60000 r--p 00017000 08:01 38797898                   /lib/x86_64-linux-gnu/libpthread-2.23.so
7fc902d60000-7fc902d61000 rw-p 00018000 08:01 38797898                   /lib/x86_64-linux-gnu/libpthread-2.23.so
7fc902d61000-7fc902d65000 rw-p 00000000 00:00 0
7fc902d65000-7fc902d8b000 r-xp 00000000 08:01 38797787                   /lib/x86_64-linux-gnu/ld-2.23.so
7fc902dc5000-7fc902f7b000 rw-p 00000000 00:00 0
7fc902f86000-7fc902f87000 rw-p 00000000 00:00 0
7fc902f87000-7fc902f88000 rwxp 00000000 00:00 0
7fc902f88000-7fc902f8a000 rw-p 00000000 00:00 0
7fc902f8a000-7fc902f8b000 r--p 00025000 08:01 38797787                   /lib/x86_64-linux-gnu/ld-2.23.so
7fc902f8b000-7fc902f8c000 rw-p 00026000 08:01 38797787                   /lib/x86_64-linux-gnu/ld-2.23.so
7fc902f8c000-7fc902f8d000 rw-p 00000000 00:00 0
7ffc38bde000-7ffc38bff000 rw-p 00000000 00:00 0                          [stack]
7ffc38cd8000-7ffc38cda000 r--p 00000000 00:00 0                          [vvar]
7ffc38cda000-7ffc38cdc000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted (core dumped)

Tags: gnuhomeinputsolinuxlibusrtype
2条回答

谢谢大家

下面是Python向Fortran传递多维数组的工作示例

python代码:

from ctypes import *
import ctypes
import sys
import os
import numpy as np

sim = cdll.LoadLibrary(os.path.dirname(os.path.abspath(__file__)) + "/lib/struct.so")


class Param( Structure ):
    pass

class Result( Structure ):
    pass

def main():

    x = 2
    y = 3
    z = 4
    Param._fields_ = [( "len_x", c_int ),
                ( "len_y", c_int ),
                ( "len_z", c_int ),
                ( "c", POINTER(c_double)),
                ( "d", POINTER(c_double * x)),
                ( "e", POINTER(c_double * x * y))]

    Result._fields_ = [( "len_x", c_int ),
                ( "len_y", c_int ),
                ( "len_z", c_int ),
                ( "f", POINTER(c_double)),
                ( "g", POINTER(c_double * x)),
                ( "h", POINTER(c_double * x * y))]

    param = Param() 
    result = Result()

    cc = (c_double * x)()
    dd = ( (c_double * x) * y )()
    ee = ( ( ( (c_double * x) * y ) * z ) )()

    #[x]    
    cc[0] = 10.0
    cc[1] = 20.0

    #[y][x]
    dd[0][0] = 10.0
    dd[1][0] = 20.0
    dd[2][0] = 30.0
    dd[0][1] = 40.0
    dd[1][1] = 50.0
    dd[2][1] = 60.0

    #[z][y][x]
    ee[0][0][0] = 1.0
    ee[1][0][0] = 2.0
    ee[2][0][0] = 3.0
    ee[0][1][0] = 4.0
    ee[1][1][0] = 5.0
    ee[2][1][0] = 6.0


    param.len_x = x
    param.len_y = y
    param.len_z = z

    param.c = cc
    param.d = dd
    param.e = ee

    sim.structtest(byref(param), byref(result))

    #[x]
    print "1D"
    print result.f[0]
    print result.f[1]

    #[y][x]
    print "2D"
    print result.g[0][0] 
    print result.g[1][0]
    print result.g[2][0] 
    print result.g[0][1] 
    print result.g[1][1] 
    print result.g[2][1] 

    #[z][y][x]
    print "3D"
    print result.h[0][0][0]
    print result.h[1][0][0]
    print result.h[2][0][0]
    print result.h[0][1][0]
    print result.h[1][1][0]
    print result.h[2][1][0]



if __name__ == "__main__":
    result = main() 

fortran代码:

^{pr2}$

输出:

 1D
   10.0000000000000
   20.0000000000000
 2D
   10.0000000000000
   20.0000000000000
   30.0000000000000
   40.0000000000000
   50.0000000000000
   60.0000000000000
 3D
   1.00000000000000
   2.00000000000000
   3.00000000000000
   4.00000000000000
   5.00000000000000
   6.00000000000000
1D
10.0
20.0
2D
10.0
20.0
30.0
40.0
50.0
60.0
3D
1.0
2.0
3.0
4.0
5.0
6.0

内存中所谓的可分配组件描述符的布局是Fortran处理器特有的。对于一个可分配的数组组件,它永远不仅仅是一个内存地址。有关描述符的详细信息,您需要查阅Fortran处理器的文档。依赖于描述符布局的代码本质上是特定于处理器的。在

“英特尔编译器”当前版本的相关文档可在Handling Fortran Array Descriptors部分找到。在

Fortran 2018的当前草案提供了与可分配伪参数进行互操作的附加功能,但仍存在特定于平台的特性。在

(在所示的代码中,您使用了内部模块ISO\u绑定,但代码似乎没有引用其中的任何内容……)

相关问题 更多 >