使用 Char 作为参数从 Fortran DLL 调用函数
Calling function from Fortran DLL with Char as parameter
我正在尝试使用 Python 从第 3 方 Fortran DLL 调用函数(冒泡排序)。我的问题是将 char 传递给函数。我使用 cffi 使其工作,如下所示,但我想使用 ctypes。
cffi 版本:
import numpy as np
import cffi as cf
ffi=cf.FFI()
lib=ffi.dlopen(r"C:\Windows\SysWOW64\DLL20DDS")
ffi.cdef("""void M01CAF( double rv[], const int *m1, const int *m2,
const wchar_t *order, int *ifail);""")
m1 = 1
m1 = ffi.new("int*", m1)
m2 = 16
m2 = ffi.new("int*", m2)
order = ffi.new('wchar_t *', "A")
rvx = np.array([1.3, 5.9, 4.1, 2.3, 0.5, 5.8, 1.3, 6.5,
2.3, 0.5, 6.5, 9.9, 2.1, 1.1, 1.2, 8.6], dtype=float, order='F')
rv = ffi.cast("double* ", rvx.__array_interface__['data'][0])
ifail = 0
ifail = ffi.new('int*', ifail)
lib.M01CAF(rv, m1, m2, order, ifail)
print(rvx)
输出:
[0.5 0.5 1.1 1.2 1.3 1.3 2.1 2.3 2.3 4.1 5.8 5.9 6.5 6.5 8.6 9.9]
现在我的 ctypes 版本:
import numpy as np
import ctypes as ct
flib = ct.WinDLL('C:\Windows\SysWOW64\DLL20DDS.dll')
func = getattr(flib, "M01CAF")
func.restype = None
m1 = (ct.c_int32)(1)
m2 = (ct.c_int32)(16)
ifail = ct.c_int32(0)
rv = np.array([1.3, 5.9, 4.1, 2.3, 0.5, 5.8, 1.3, 6.5,
2.3, 0.5, 6.5, 9.9, 2.1, 1.1, 1.2, 8.6], dtype=ct.c_double, order='F')
order = 'A'
order = ct.c_wchar_p(order)
func.argtypes = (np.ctypeslib.ndpointer(dtype=ct.c_double, shape=(m2.value,)),
ct.POINTER(ct.c_int32), ct.POINTER(ct.c_int32),
ct.c_wchar_p, ct.POINTER(ct.c_int32))
func(rv, m1, m2, order, ifail)
错误信息:
OSError: exception: access violation writing 0xFFFFFFFC
______________________________________________________
我在使用 cffi 时遇到的一个问题是:当我再次调用该函数时,它不会对数组进行排序。我需要重新启动内核才能获得正确的结果:
rvx = np.array([1.3, 5.9, 4.1, 2.3, 0.5, 5.8, 1.3, 6.5,
2.3, 0.5, 6.5, 9.9, 2.1, 1.1, 1.2, 8.6], dtype=float, order='F')
rv = ffi.cast("double* ", rvx.__array_interface__['data'][0])
lib.M01CAF(rv, m1, m2, order, ifail)
print(rvx)
输出:
[1.3 5.9 4.1 2.3 0.5 5.8 1.3 6.5 2.3 0.5 6.5 9.9 2.1 1.1 1.2 8.6]
______________________________________________________
现在我在 Win10 64 位上使用 Python 3.8.3 32 位的 Spyder。
通过在 char 本身的指针之后将 char 的长度作为常规整数(不是指针)传递来解决所有问题。 CFFI也一样。
## CTYPES
import ctypes as ct
flib = ct.WinDLL('C:\Windows\SysWOW64\DLL20DDS.dll')
func = getattr(flib, "M01CAF")
func.restype = None
m1 = (ct.c_int32)(1)
m2 = (ct.c_int32)(16)
ifail = ct.c_int32(0)
rv = np.array([1.3, 5.9, 4.1, 2.3, 0.5, 5.8, 1.3, 6.5,
2.3, 0.5, 6.5, 9.9, 2.1, 1.1, 1.2, 8.6], dtype=ct.c_double, order='F')
order = ct.c_wchar_p('A')
func.argtypes = (np.ctypeslib.ndpointer(dtype=ct.c_double, shape=(m2.value,)),
ct.POINTER(ct.c_int32), ct.POINTER(ct.c_int32),
ct.c_wchar_p, ct.c_int32, ct.POINTER(ct.c_int32))
print("BEFORE:")
print(rv)
func(rv, m1, m2, order, 1, ifail)
print("AFTER:")
print(rv)
我正在尝试使用 Python 从第 3 方 Fortran DLL 调用函数(冒泡排序)。我的问题是将 char 传递给函数。我使用 cffi 使其工作,如下所示,但我想使用 ctypes。
cffi 版本:
import numpy as np
import cffi as cf
ffi=cf.FFI()
lib=ffi.dlopen(r"C:\Windows\SysWOW64\DLL20DDS")
ffi.cdef("""void M01CAF( double rv[], const int *m1, const int *m2,
const wchar_t *order, int *ifail);""")
m1 = 1
m1 = ffi.new("int*", m1)
m2 = 16
m2 = ffi.new("int*", m2)
order = ffi.new('wchar_t *', "A")
rvx = np.array([1.3, 5.9, 4.1, 2.3, 0.5, 5.8, 1.3, 6.5,
2.3, 0.5, 6.5, 9.9, 2.1, 1.1, 1.2, 8.6], dtype=float, order='F')
rv = ffi.cast("double* ", rvx.__array_interface__['data'][0])
ifail = 0
ifail = ffi.new('int*', ifail)
lib.M01CAF(rv, m1, m2, order, ifail)
print(rvx)
输出:
[0.5 0.5 1.1 1.2 1.3 1.3 2.1 2.3 2.3 4.1 5.8 5.9 6.5 6.5 8.6 9.9]
现在我的 ctypes 版本:
import numpy as np
import ctypes as ct
flib = ct.WinDLL('C:\Windows\SysWOW64\DLL20DDS.dll')
func = getattr(flib, "M01CAF")
func.restype = None
m1 = (ct.c_int32)(1)
m2 = (ct.c_int32)(16)
ifail = ct.c_int32(0)
rv = np.array([1.3, 5.9, 4.1, 2.3, 0.5, 5.8, 1.3, 6.5,
2.3, 0.5, 6.5, 9.9, 2.1, 1.1, 1.2, 8.6], dtype=ct.c_double, order='F')
order = 'A'
order = ct.c_wchar_p(order)
func.argtypes = (np.ctypeslib.ndpointer(dtype=ct.c_double, shape=(m2.value,)),
ct.POINTER(ct.c_int32), ct.POINTER(ct.c_int32),
ct.c_wchar_p, ct.POINTER(ct.c_int32))
func(rv, m1, m2, order, ifail)
错误信息:
OSError: exception: access violation writing 0xFFFFFFFC
______________________________________________________
我在使用 cffi 时遇到的一个问题是:当我再次调用该函数时,它不会对数组进行排序。我需要重新启动内核才能获得正确的结果:
rvx = np.array([1.3, 5.9, 4.1, 2.3, 0.5, 5.8, 1.3, 6.5,
2.3, 0.5, 6.5, 9.9, 2.1, 1.1, 1.2, 8.6], dtype=float, order='F')
rv = ffi.cast("double* ", rvx.__array_interface__['data'][0])
lib.M01CAF(rv, m1, m2, order, ifail)
print(rvx)
输出:
[1.3 5.9 4.1 2.3 0.5 5.8 1.3 6.5 2.3 0.5 6.5 9.9 2.1 1.1 1.2 8.6]
______________________________________________________
现在我在 Win10 64 位上使用 Python 3.8.3 32 位的 Spyder。
通过在 char 本身的指针之后将 char 的长度作为常规整数(不是指针)传递来解决所有问题。 CFFI也一样。
## CTYPES
import ctypes as ct
flib = ct.WinDLL('C:\Windows\SysWOW64\DLL20DDS.dll')
func = getattr(flib, "M01CAF")
func.restype = None
m1 = (ct.c_int32)(1)
m2 = (ct.c_int32)(16)
ifail = ct.c_int32(0)
rv = np.array([1.3, 5.9, 4.1, 2.3, 0.5, 5.8, 1.3, 6.5,
2.3, 0.5, 6.5, 9.9, 2.1, 1.1, 1.2, 8.6], dtype=ct.c_double, order='F')
order = ct.c_wchar_p('A')
func.argtypes = (np.ctypeslib.ndpointer(dtype=ct.c_double, shape=(m2.value,)),
ct.POINTER(ct.c_int32), ct.POINTER(ct.c_int32),
ct.c_wchar_p, ct.c_int32, ct.POINTER(ct.c_int32))
print("BEFORE:")
print(rv)
func(rv, m1, m2, order, 1, ifail)
print("AFTER:")
print(rv)