Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
指定ctypes调用(在python中)的返回类型,该调用用于返回double数组的fortran函数_Python_Fortran_Ctypes - Fatal编程技术网

指定ctypes调用(在python中)的返回类型,该调用用于返回double数组的fortran函数

指定ctypes调用(在python中)的返回类型,该调用用于返回double数组的fortran函数,python,fortran,ctypes,Python,Fortran,Ctypes,我试图使用ctypes模块从python程序中调用我编写的线性代数例程(fortran)库。我已成功导入库,并可以调用返回单个值的子程序和函数。我的问题是调用返回双精度数组的函数。我不知道如何指定返回类型。因此,每当我调用这样的函数时,都会出现SEGFULTS 下面是一个最小的工作示例,一个获取两个3向量之间的叉积的例程: !**************************************************************************************

我试图使用ctypes模块从python程序中调用我编写的线性代数例程(fortran)库。我已成功导入库,并可以调用返回单个值的子程序和函数。我的问题是调用返回双精度数组的函数。我不知道如何指定返回类型。因此,每当我调用这样的函数时,都会出现SEGFULTS

下面是一个最小的工作示例,一个获取两个3向量之间的叉积的例程:

!****************************************************************************************
! Given vectors a and b, c = a x b
function cross_product(a,b)
real(dp) a(3), b(3), cross_product(3)

cross_product = (/a(2)*b(3) - a(3)*b(2), &
                  a(3)*b(1) - a(1)*b(3), &
                  a(1)*b(2) - a(2)*b(1)/)
end function cross_product
下面是我的python脚本:

#!/usr/bin/python
from ctypes import byref, cdll, c_double
testlib =  cdll.LoadLibrary('/Users/hart/codes/celib/trunk/libutils.so')
cross = testlib.vector_matrix_utilities_mp_cross_product_

a = (c_double * 3)()
b = (c_double * 3)()
a[0] = c_double(0.0)
a[1] = c_double(1.0)
a[2] = c_double(2.0)
b[0] = c_double(1.0)
b[1] = c_double(3.0)
b[2] = c_double(2.0)

print a,b
cross.restype = c_double * 3
print cross.restype
print cross(byref(a),byref(b))
以下是输出:

goku:~/python/ctypes> ./test_example.py 
<__main__.c_double_Array_3 object at 0x10399b710> <__main__.c_double_Array_3 object at 0x10399b7a0>
<class '__main__.c_double_Array_3'>
Segmentation fault: 11
goku:~/python/ctypes>
goku:~/python/ctypes>/test\u example.py
分段错误:11
小悟空:~/python/ctypes>

我尝试了对“cross.restype=…”行的不同排列,但我不知道实际应该是什么。谢谢你阅读这个问题--Gus

编译器可能会返回指向数组的指针或数组描述符。。。因此,在混合语言时,应该始终使用
bind(C)
,除非包装器特别支持Fortran。而且(毫不奇怪)
bind(C)
函数不能返回数组。从理论上讲,您可以分配数组并将
type(c_ptr)
返回给它,但是使用后如何取消分配呢


所以我的建议是使用一个子例程。

编译器可能会返回指向数组的指针,或者数组描述符。。。因此,在混合语言时,应该始终使用
bind(C)
,除非包装器特别支持Fortran。而且(毫不奇怪)
bind(C)
函数不能返回数组。从理论上讲,您可以分配数组并将
type(c_ptr)
返回给它,但是使用后如何取消分配呢


因此,我的建议是使用一个子例程。

对于gfortran,函数调用有一个隐藏参数:

>>> from ctypes import *
>>> testlib = CDLL('./libutils.so')
>>> cross = testlib.cross_product_

>>> a = (c_double * 3)(*[0.0, 1.0, 2.0])
>>> b = (c_double * 3)(*[1.0, 3.0, 2.0])
>>> c = (c_double * 3)()
>>> pc = pointer(c)

>>> cross(byref(pc), a, b)
3
>>> c[:]
[-4.0, 2.0, -1.0]
但是使用
bind(C)
和子例程是更好的方法


仅供参考,数组成为C函数调用中的指针,因此使用
byref
是多余的。我需要
byref
pointer
为隐藏参数创建
double**

使用gfortran,函数调用有一个隐藏参数:

>>> from ctypes import *
>>> testlib = CDLL('./libutils.so')
>>> cross = testlib.cross_product_

>>> a = (c_double * 3)(*[0.0, 1.0, 2.0])
>>> b = (c_double * 3)(*[1.0, 3.0, 2.0])
>>> c = (c_double * 3)()
>>> pc = pointer(c)

>>> cross(byref(pc), a, b)
3
>>> c[:]
[-4.0, 2.0, -1.0]
但是使用
bind(C)
和子例程是更好的方法


仅供参考,数组成为C函数调用中的指针,因此使用
byref
是多余的。我需要
byref
pointer
为隐藏参数创建
double**

您不使用它有什么原因吗?@SethMMorton,因为它无法处理派生数据类型。我的代码非常“现代”,有很多“对象”,而不仅仅是数字和数组。对于派生数据类型,这个包在大多数情况下似乎都能做到这一点。您不使用@SethMMorton有什么原因吗?因为它无法处理派生数据类型。我的代码非常“现代”,有很多“对象”,而不仅仅是数字和数组。对于派生数据类型,这个包在大多数情况下似乎都能做到这一点。我有很多我想从python调用的代码。在我的例子中,重新编写它以避免派生数据类型并始终位于子例程中不是一个非常实用的解决方案。然而,这个新的包装器似乎可以在许多(但不是所有)实例中使用。你甚至可以把它作为一个答案发布,并添加一些评论。直到今天我才知道这个软件包。我有很多我想从python调用的代码。在我的例子中,重新编写它以避免派生数据类型并始终位于子例程中不是一个非常实用的解决方案。然而,这个新的包装器似乎可以在许多(但不是所有)实例中使用。你甚至可以把它作为一个答案发布,并添加一些评论。直到今天我才知道这个包裹。