由Python向Fortran中传输字符串

PythonFortran中传输字符串

1.原理介绍

image.png
  1. python中所有的字符串默认为Unicode字符串,故可以通过encode()decode()方法进行转换。

  2. 字符串数组在ctypes中的行为更接近于C语言中的字符串数组,其需要采用二维数组的形式来实现,e.g. ((c_char * 10) * 3)()


print("1-------------------") 

charList = ((c_char * 10) * 1)() 

print(chaeList[0].value) 

print(charList[0].raw) 

print("2-------------------") 

strList = ['a一α'] 

charList[0] = ctypes.create_string_buffer(strList[0].encode(), 10) 



print("3-------------------") 

print(chaeList[0].value) 

print(charList[0].raw) 



# 输出结果 \xe4\xb8\x80 是"一".encode(), xce\xb1 是"α".encode()

>>1-------------------

>>b''

>>b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

>>2-------------------

>>3-------------------

b'a\xe4\xb8\x80\xce\xb1'

b'a\xe4\xb8\x80\xce\xb1\x00\x00\x00\x00'

  1. 上述的字符串数组实例可直接当做字符串指针传入C函数,其行为等同于在C中声明的 char (*)[10]指针

  2. 由于ctypes的字符串对象通过某个固定长度的字符串类实例化得到,故在赋值时,这样的字符串对象只可以接受等同于其声明长度的字符串对象作为替代值,这是普通Python字符串做不到的。要得到这样的定长字符串,需要用到ctypescreate_string_buffer函数。create_string_buffer函数用于创建固定长度的带缓冲字符串。其接受两个参数,第一参数为字符串,第二参数为目标长度,返回值即为被创建的定长度字符串对象,可以赋值给字符串数组中的某个对象。注意,create_string_buffer函数必须接受字节字符串作为其第一参数。

方法一

无需Fortran中需要预先分配大空间character,但是需要传入两个参数


subroutine writepath(x,N) bind(C, name="wPath")

    use ISO_C_BINDING

    implicit none

    integer(c_int), intent(in), value  :: N

    character(kind=c_char) :: x(N)

write(*,*) x(1:N)

end subroutine


from ctypes import create_string_buffer, c_char, c_int

def string2fortran(strs):

    lenStrs = len(strs.encode())

    charList = ((c_char * lenStrs) * 1)() 

    charList[0] = create_string_buffer(strs.encode(), lenStrs) 

    return charList[0], c_int(lenStrs)

import ctypes as ct

fortlib = ct.CDLL(r'路径/动态链接库.dll')

writePath = getattr(fortlib, "wPath") 

writePath.argtypes = [ct.POINTER(ct.c_char), ct.c_int]

filepath_chinese = r'字符串'

filepath, filepath_length = string2fortran(filepath_chinese) 

writePath(filepath, filepath_length)

方法二

需要Fortran中需要预先分配大空间character,只需要传入一个参数


subroutine writePath(x) bind(C, name="writePath")

    use ISO_C_BINDING

    implicit none

    character(kind=c_char), target :: x(9999) ! target 形容词不能少

    character(9999), pointer :: ps=>null()

    integer(kind=4) :: lens



    call c_f_pointer(c_loc(x(1)),ps)

    lens = index(ps, c_null_char)-1

    write(*,*) ps(1:lens)



end subroutine


from ctypes import create_string_buffer, c_char

def string2fortran(strs):

    lenStrs = len(strs.encode())

    charList = ((c_char * lenStrs) * 1)() 

    charList[0] = create_string_buffer(strs.encode(), lenStrs) 

    return charList[0]

import ctypes as ct

fortlib = ct.CDLL(r'路径/动态链接库.dll')

writePath = getattr(fortlib, "writePath") 

writePath.argtypes = [ct.POINTER(ct.c_char)]

filepath_chinese = r'字符串'

filepath = string2fortran(filepath_chinese) 

writePath(filepath)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容