使用f2py将numpy字符串格式数组传递给fortran

时间:2014-03-10 06:09:58

标签: python arrays numpy fortran f2py

我的目标是从fortran中的python numpy数组中打印第二个字符串,但我只打印第一个字符,并且它也不一定是正确的字符串。

有谁能告诉我将完整字符串数组传递给fortran的正确方法是什么?

代码如下:

testpy.py

import numpy as np
import testa4

strvar = np.asarray(['aa','bb','cc'], dtype = np.dtype('a2'))
testa4.testa4(strvar)

testa4.f90

subroutine testa4(strvar)
implicit none

character(len=2), intent(in) :: strvar(3)
!character*2 does not work here - why?

print *, strvar(2)

end subroutine testa4

已编译

f2py -c -m testa4 testa4.f90

输出上述代码

c

所需的输出

bb

3 个答案:

答案 0 :(得分:3)

我不知道如何使用f2py来做到这一点。但可以使用ctypes完成。你得到一个字符数组,但你可以很容易地将它转换为字符串。

subroutine testa4(strvar) bind(C, name='testa4')
  use iso_c_binding
  implicit none

  character(len=1,kind=c_char), intent(in) :: strvar(2,3)

  print *, strvar(:,2)

end subroutine testa4

编译:{{1​​}}

gfortran -shared -fPIC testa4.f90 -o testa4.so

运行:

import numpy as np
import ctypes

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

strvar = np.asarray(['aa','bb','cc'], dtype = np.dtype('a2'))
strvar_p = ctypes.c_void_p(strvar.ctypes.data)

testa4.testa4(strvar_p)

答案 1 :(得分:3)

根据documentation,f2py喜欢用dtype ='c'传递的字符串数组(即'| S1')。这会让你成为那里的一部分,虽然在幕后有一些奇怪的阵列形状(例如,在我的很多测试中,我发现fortran会保留2个字符的长度,但是将6个字符解释为指示一个2x6阵列,所以我会在输出中得到随机存储器)。这(据我所知),要求您将Fortran数组视为2D字符数组(而不是1D“字符串”数组)。不幸的是,我无法让它采取假定的形状,并最终将字符串的数量作为参数传递。

我很确定我错过了一些相当明显的东西,但这应该暂时有效。至于为什么CHARACTER * 2不起作用......我真的不知道。

MODULE char_test

CONTAINS

SUBROUTINE print_strings(strings, n_strs)
    IMPLICIT NONE

    ! Inputs
    INTEGER, INTENT(IN) :: n_strs
    CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings

!f2py INTEGER, INTENT(IN) :: n_strs
!f2py CHARACTER, INTENT(IN), DIMENSION(2,n_strs) :: strings

    ! Misc.
    INTEGER*4 :: j


    DO j=1, n_strs
        WRITE(*,*) strings(:,j)
    END DO

END SUBROUTINE print_strings

END MODULE char_test

----------------

import numpy as np
import char_test as ct

strings = np.array(['aa', 'bb', 'cc'], dtype='c').T
ct.char_test.print_strings(strings, strings.shape[1])

strings = np.array(['ab', 'cd', 'ef'], dtype='c').T
ct.char_test.print_strings(strings, strings.shape[1]) 

-->python run_char_test.py
 aa
 bb
 cc
 ab
 cd
 ef

答案 2 :(得分:0)

不是答案,但是评论时间太长:也许这会有所帮助..

在你的第一种情况下传递给fortran的是由于某种原因每个字符串的第一个字符:

'abc'

在fortran中,在长度为2的数组中结束为' ab' ,' c'。如果你严格地使用长度一个字符串阵列一切都很好,我想。不幸的是你不能伪造系统并在python ['a','a','b','b'..中分成单个字符数组 - 如果数组长度不匹配则会抛出错误。

关于第二个问题,如果您使用

声明
  character*2

符号,它实际上只是传递一个常规的python字符串列表:

  testa4.testa4(['aa','bb','cc'])

(如果您尝试使用numpy字符串数组,现在会抛出错误。)。字符串必须是正确的正确长度,否则它也会引发错误。