无法从 ctypes 获取 Fortran 函数输出
Can't get fortran function output from ctypes
我正在尝试使用 ctypes 从 Python 调用 Fortran 函数。我试图从子例程和函数(都具有相同的功能)获得结果,但我无法从函数获得预期的输出,而子例程运行良好。
问题是我有很多带有 Fortran 函数而不是子例程的库。
Fortran函数和ctypes有什么问题吗?
一段 Fortran 代码:
MODULE Vector
! Public types
TYPE VectorType
PRIVATE
DOUBLE PRECISION, DIMENSION(3):: components = 0.0d0
END TYPE VectorType
!---------------------------------------------------------------------
CONTAINS
!---------------------------------------------------------------------
SUBROUTINE newVect(this,vectorIn)
TYPE (VectorType), INTENT(OUT):: this
DOUBLE PRECISION, DIMENSION(3), INTENT(IN)::vectorIn
this%components = (/vectorIn(1), vectorIn(2), vectorIn(3)/)
END SUBROUTINE newVect
!---------------------------------------------------------------------
SUBROUTINE subVect(this,vectorOut)
TYPE(VectorType), INTENT (OUT):: vectorOut
TYPE(VectorType), INTENT (IN) :: this
vectorOut%components = this%components
END SUBROUTINE subVect
!----------------------------------------------------------------------
TYPE(VectorType) FUNCTION getVect(this) RESULT(vectorOut)
TYPE(VectorType), INTENT (IN) :: this
vectorOut%components = this%components
END FUNCTION getVect
!--------------------------------------------------------------------
END MODULE Vector
我使用的 Python 代码是:
import ctypes
import numpy as np
class _VectorType(ctypes.Structure):
_fields_ = [('components', ctypes.c_double*3)]
lib_gen_ctypes = '/local/scratch/jfreixa/lib/lib_ctypes_vector.so'
try_ctypes = ctypes.CDLL(lib_gen_ctypes,ctypes.RTLD_GLOBAL)
class vector(object):
_ctypes_newVect = try_ctypes['Vector.newVect_']
_ctypes_subVect = try_ctypes['Vector._subVect_']
_ctypes_getVect = try_ctypes['Vector.getVect_']
vector_pointer = ctypes.POINTER(_VectorType)
_ctypes_getVect.argtypes = [vector_pointer,]
_ctypes_getVect.restype = _VectorType
def __init__(self,*args):
self._vector = _VectorType()
self._newVect(*args)
def _newVect(self,vectIn):
pdb.set_trace()
c_vect = (ctypes.c_double*3)(*vectIn)
self._ctypes_newVect(self._vector,c_vect)
def subVect(self):
pdb.set_trace()
c_vect = _VectorType()
self._ctypes_subVect(ctypes.byref(self._vector),ctypes.byref(c_vect))
print c_vect.components[:]
return np.array(c_vect.components[:])
def getVect(self):
pdb.set_trace()
c_vect = self._ctypes_getVect(ctypes.byref(self._vector))
vect = self._ctypes_getVect(self.vector_pointer.from_address(ctypes.addressof(c_vect)))
print vect.components[:]
return np.array(vect.components[:])
为了这个功能我试了很多东西,但我从来没有得到正确的结果。要 运行 程序片段尝试:
import pyctp.vector
newVect = pyctp.vector.vector((1.0,2.0,3.0))
newVect.subVect()
newVect.getVect()
子例程调用 returns 预期向量,而函数调用 returns 空向量或充满垃圾的向量。
首先,您应该将 bind(C) 属性添加到您希望在 Python 中可见的所有过程和类型。
所有 Fortran 类型都应取自 iso_c_binding,例如使用 real(c_double)
而不是 double precision
您将确保它是可与 C 互操作的类型。
MODULE Vector
use iso_c_binding
! Public types
TYPE,bind(C) :: VectorType
real(c_double), DIMENSION(3):: components = 0.0d0
END TYPE VectorType
CONTAINS
!---------------------------------------------------------------------
SUBROUTINE newVect(this,vectorIn) bind(c,name="newVect")
TYPE (VectorType), INTENT(OUT):: this
real(c_double), DIMENSION(3), INTENT(IN)::vectorIn
this%components = (/vectorIn(1), vectorIn(2), vectorIn(3)/)
END SUBROUTINE newVect
!---------------------------------------------------------------------
SUBROUTINE subVect(this,vectorOut) bind(c,name="subVect")
TYPE(VectorType), INTENT (OUT):: vectorOut
TYPE(VectorType), INTENT (IN) :: this
vectorOut%components = this%components
END SUBROUTINE subVect
!----------------------------------------------------------------------
TYPE(VectorType) FUNCTION getVect(this) RESULT(vectorOut) bind(c,name="getVect")
TYPE(VectorType), INTENT (IN) :: this
vectorOut%components = this%components
END FUNCTION getVect
!--------------------------------------------------------------------
END MODULE Vector
然后在python中传递所有参数作为参考:
import ctypes
import numpy as np
class _VectorType(ctypes.Structure):
_fields_ = [('components', ctypes.c_double*3)]
lib_gen_ctypes = 'lib_ctypes_vector.so'
try_ctypes = ctypes.CDLL(lib_gen_ctypes,ctypes.RTLD_GLOBAL)
class vector(object):
_ctypes_newVect = try_ctypes['newVect']
_ctypes_subVect = try_ctypes['subVect']
_ctypes_getVect = try_ctypes['getVect']
vector_pointer = ctypes.POINTER(_VectorType)
_ctypes_getVect.argtypes = [vector_pointer,]
_ctypes_getVect.restype = _VectorType
def __init__(self,*args):
self._vector = _VectorType()
self._newVect(*args)
def _newVect(self,vectIn):
c_vect = (ctypes.c_double*3)(*vectIn)
self._ctypes_newVect(ctypes.byref(self._vector),ctypes.byref(c_vect))
def subVect(self):
c_vect = _VectorType()
self._ctypes_subVect(ctypes.byref(self._vector),ctypes.byref(c_vect))
return np.array(c_vect.components[:])
def getVect(self):
c_vect = self._ctypes_getVect(ctypes.byref(self._vector))
return np.array(vect.components[:])
getVect 的结果已经是 VectorType,因此您可以直接访问其组件。
我正在尝试使用 ctypes 从 Python 调用 Fortran 函数。我试图从子例程和函数(都具有相同的功能)获得结果,但我无法从函数获得预期的输出,而子例程运行良好。 问题是我有很多带有 Fortran 函数而不是子例程的库。 Fortran函数和ctypes有什么问题吗?
一段 Fortran 代码:
MODULE Vector
! Public types
TYPE VectorType
PRIVATE
DOUBLE PRECISION, DIMENSION(3):: components = 0.0d0
END TYPE VectorType
!---------------------------------------------------------------------
CONTAINS
!---------------------------------------------------------------------
SUBROUTINE newVect(this,vectorIn)
TYPE (VectorType), INTENT(OUT):: this
DOUBLE PRECISION, DIMENSION(3), INTENT(IN)::vectorIn
this%components = (/vectorIn(1), vectorIn(2), vectorIn(3)/)
END SUBROUTINE newVect
!---------------------------------------------------------------------
SUBROUTINE subVect(this,vectorOut)
TYPE(VectorType), INTENT (OUT):: vectorOut
TYPE(VectorType), INTENT (IN) :: this
vectorOut%components = this%components
END SUBROUTINE subVect
!----------------------------------------------------------------------
TYPE(VectorType) FUNCTION getVect(this) RESULT(vectorOut)
TYPE(VectorType), INTENT (IN) :: this
vectorOut%components = this%components
END FUNCTION getVect
!--------------------------------------------------------------------
END MODULE Vector
我使用的 Python 代码是:
import ctypes
import numpy as np
class _VectorType(ctypes.Structure):
_fields_ = [('components', ctypes.c_double*3)]
lib_gen_ctypes = '/local/scratch/jfreixa/lib/lib_ctypes_vector.so'
try_ctypes = ctypes.CDLL(lib_gen_ctypes,ctypes.RTLD_GLOBAL)
class vector(object):
_ctypes_newVect = try_ctypes['Vector.newVect_']
_ctypes_subVect = try_ctypes['Vector._subVect_']
_ctypes_getVect = try_ctypes['Vector.getVect_']
vector_pointer = ctypes.POINTER(_VectorType)
_ctypes_getVect.argtypes = [vector_pointer,]
_ctypes_getVect.restype = _VectorType
def __init__(self,*args):
self._vector = _VectorType()
self._newVect(*args)
def _newVect(self,vectIn):
pdb.set_trace()
c_vect = (ctypes.c_double*3)(*vectIn)
self._ctypes_newVect(self._vector,c_vect)
def subVect(self):
pdb.set_trace()
c_vect = _VectorType()
self._ctypes_subVect(ctypes.byref(self._vector),ctypes.byref(c_vect))
print c_vect.components[:]
return np.array(c_vect.components[:])
def getVect(self):
pdb.set_trace()
c_vect = self._ctypes_getVect(ctypes.byref(self._vector))
vect = self._ctypes_getVect(self.vector_pointer.from_address(ctypes.addressof(c_vect)))
print vect.components[:]
return np.array(vect.components[:])
为了这个功能我试了很多东西,但我从来没有得到正确的结果。要 运行 程序片段尝试:
import pyctp.vector
newVect = pyctp.vector.vector((1.0,2.0,3.0))
newVect.subVect()
newVect.getVect()
子例程调用 returns 预期向量,而函数调用 returns 空向量或充满垃圾的向量。
首先,您应该将 bind(C) 属性添加到您希望在 Python 中可见的所有过程和类型。
所有 Fortran 类型都应取自 iso_c_binding,例如使用 real(c_double)
而不是 double precision
您将确保它是可与 C 互操作的类型。
MODULE Vector
use iso_c_binding
! Public types
TYPE,bind(C) :: VectorType
real(c_double), DIMENSION(3):: components = 0.0d0
END TYPE VectorType
CONTAINS
!---------------------------------------------------------------------
SUBROUTINE newVect(this,vectorIn) bind(c,name="newVect")
TYPE (VectorType), INTENT(OUT):: this
real(c_double), DIMENSION(3), INTENT(IN)::vectorIn
this%components = (/vectorIn(1), vectorIn(2), vectorIn(3)/)
END SUBROUTINE newVect
!---------------------------------------------------------------------
SUBROUTINE subVect(this,vectorOut) bind(c,name="subVect")
TYPE(VectorType), INTENT (OUT):: vectorOut
TYPE(VectorType), INTENT (IN) :: this
vectorOut%components = this%components
END SUBROUTINE subVect
!----------------------------------------------------------------------
TYPE(VectorType) FUNCTION getVect(this) RESULT(vectorOut) bind(c,name="getVect")
TYPE(VectorType), INTENT (IN) :: this
vectorOut%components = this%components
END FUNCTION getVect
!--------------------------------------------------------------------
END MODULE Vector
然后在python中传递所有参数作为参考:
import ctypes
import numpy as np
class _VectorType(ctypes.Structure):
_fields_ = [('components', ctypes.c_double*3)]
lib_gen_ctypes = 'lib_ctypes_vector.so'
try_ctypes = ctypes.CDLL(lib_gen_ctypes,ctypes.RTLD_GLOBAL)
class vector(object):
_ctypes_newVect = try_ctypes['newVect']
_ctypes_subVect = try_ctypes['subVect']
_ctypes_getVect = try_ctypes['getVect']
vector_pointer = ctypes.POINTER(_VectorType)
_ctypes_getVect.argtypes = [vector_pointer,]
_ctypes_getVect.restype = _VectorType
def __init__(self,*args):
self._vector = _VectorType()
self._newVect(*args)
def _newVect(self,vectIn):
c_vect = (ctypes.c_double*3)(*vectIn)
self._ctypes_newVect(ctypes.byref(self._vector),ctypes.byref(c_vect))
def subVect(self):
c_vect = _VectorType()
self._ctypes_subVect(ctypes.byref(self._vector),ctypes.byref(c_vect))
return np.array(c_vect.components[:])
def getVect(self):
c_vect = self._ctypes_getVect(ctypes.byref(self._vector))
return np.array(vect.components[:])
getVect 的结果已经是 VectorType,因此您可以直接访问其组件。