首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用f2py将字符串数组传递给Fortran子例程

如何使用f2py将字符串数组传递给Fortran子例程
EN

Stack Overflow用户
提问于 2017-01-26 10:20:53
回答 3查看 1.2K关注 0票数 2

经过一些网上挖掘和试错之后,我仍然想知道如何通过f2py将字符串数组从Python传递到Fortran。

我在string.f90中有Fortran子例程,如下所示:

代码语言:javascript
复制
  SUBROUTINE FOO(A)
  CHARACTER*5,dimension(10),intent(inout):: A
  PRINT*, "A=",A
  END

然后我运行f2py -m mystring -c string.f90。编译成功。

python会话在test.py

代码语言:javascript
复制
import mystring
import numpy as np
nobstot=10
xstring=np.empty(nobstot,dtype='S5')
xstring[0]="ABCDE"
mystring.foo(xstring)

运行python test.py,我会看到以下错误消息:

代码语言:javascript
复制
1-th dimension must be 5 but got 0 (not defined).
Traceback (most recent call last) :
File "test.py", line 6, in <module>
mystring.foo(xstring)
mystring.error: failed in converting 1st argument `a' of mystring.foo to C/Fortran array

在f2py编译步骤中,调用了gfortran和gcc编译器。

>>> print mystring.foo.__doc__之后,出现了:

代码语言:javascript
复制
foo(a)
Wrapper for ``foo``.
Parameters
---------
a : in/output rank-2 array('S') with bounds (10,5)

因此,我尝试了test.py

代码语言:javascript
复制
import mystring
import numpy as np
nobstot=10
xstring=np.empty((nobstot,5),dtype='S1')
print xstring.shape
xstring[0]="ABCDE"
mystring.foo(xstring)

然后运行python test.py,错误消息为:

代码语言:javascript
复制
Traceback (most recent call last):
File "test.py", line 7, in <module>
mystring.foo(xstring)
ValueError: failed to initialize intent(inout) array -- input 'S' not compatible to 'c'
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-01-27 18:14:45

首先,要将字符串数组传递给f2py,在Python语言中,必须创建一个具有(<number of strings>, <string length>)形状的字符数组,填充其内容,然后将字符数组传递给Fortran生成的函数。使用您的示例:

代码语言:javascript
复制
xstring = np.empty((nobstot, 5), dtype='c')
xstring[0] = "ABCDE"
xstring[1] = "FGHIJ"
mystring.foo(xstring)

为了使其正常工作,您还需要更改Fortran代码:

代码语言:javascript
复制
subroutine foo(A)
character*5, dimension(10), intent(in) :: A
print*, "A(1)=",A(1)
print*, "A(2)=",A(2)
end

请注意,intent(inout)已替换为intent(in)。这是因为Python中的字符串以及numpy字符串数组中的字符串是不可变的,但在Fortran中可能不是。因此,Python字符串的内存布局不能简单地传递给Fortran函数,用户必须如上所述重新组织字符串数据。

其次,如果Fortran代码更改了字符串,如intent(inout)的用法所示,则需要将这样的字符串参数声明为intent(in, out),例如,使用f2py指令。下面是一个完整的示例:

代码语言:javascript
复制
subroutine foo(A)
character*5, dimension(10), intent(inout) :: A
!f2py intent(in, out) A
print*, "A(1)=",A(1)
print*, "A(2)=",A(2)
A(1)="QWERT"
end

F2py调用:

代码语言:javascript
复制
f2py -m mystring -c string.f90

Python测试脚本:

代码语言:javascript
复制
import mystring
import numpy as np
nobstot = 10
xstring = np.empty((nobstot, 5), dtype='c')
xstring[0] = "ABCDE"
xstring[1] = "FGHIJ"
xstring = mystring.foo(xstring)
print("xstring[0]=",string[0].tostring())
print("xstring[1]=",string[1].tostring())

控制台输出:

代码语言:javascript
复制
 A(1)=ABCDE
 A(2)=FGHIJ
xstring[0]= QWERT
xstring[1]= FGHIJ
票数 2
EN

Stack Overflow用户

发布于 2017-01-27 06:57:28

在fortran中来回传递字符串有点棘手。

通过这一行,您建立了一个实用的二维字符数组10 *5

代码语言:javascript
复制
CHARACTER*5,dimension(10),intent(inout):: A

尝试将其更改为

代码语言:javascript
复制
CHARACTER*10,intent(inout):: A

这使它成为一个由10个字符组成的一维数组。如果它可以工作,但输出是垃圾,请检查两者是否为相同的字符格式(ascii/multibyte或unicode)。

票数 0
EN

Stack Overflow用户

发布于 2021-07-06 05:40:54

这个@Pearu行得通吗?用ord转换ASCII int,直接发送->数组

代码语言:javascript
复制
xstring = np.zeros((10, 5)).astype(int)
strings = ["ABCDE","FGHIJ"]
for istring,string in enumerate(strings):
   for ichar,char in enumerate(string):
      xstring[istring,ichar] = ord(char)
 
mystring.foo(xstring)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41864984

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档