Fortran(90)代码如下:
! fortranDLLExample.f90
!
! FUNCTIONS/SUBROUTINES exported from fortranDLLExample.dll:
! fortranDLLExample - subroutine
FUNCTION ABZERO(P) bind(C,name="ABZERO")
!DEC$ ATTRIBUTES DLLEXPORT :: ABZERO
!DEC$ ATTRIBUTES VALUE :: P
integer, INTENT(IN) :: P
integer :: ABZERO
integer :: result1
! Examle calculation
result1 = P - 273
print *, "The p==", P, ";"
print *, "The p-273 [", result1, "]"
ABZERO = result1
RETURN
END FUNCTION
FUNCTION ABZERO_FLOAT(P) bind(C,name="ABZERO_FLOAT")
!DEC$ ATTRIBUTES DLLEXPORT :: ABZERO_FLOAT
!DEC$ ATTRIBUTES VALUE :: P
real, INTENT(IN) :: P
real :: ABZERO_FLOAT
real :: result1
! Examle calculation
result1 = P - 273.15
print *, "The p==", P, ";"
print *, "The p-273 [", result1, "]"
ABZERO_FLOAT = P - 273.15
RETURN
END FUNCTION
FUNCTION sum(length1, P) bind(C,name="sum")
!DEC$ ATTRIBUTES DLLEXPORT :: sum
implicit none
integer::length1
real, dimension(*):: P
real :: sum
integer::i
print *, "The length1==", length1, ";"
sum =0.0
do i = 1,length1 ! sum the array elements
sum = sum + p(i)
PRINT *,p(i)
end do
RETURN
END FUNCTION
subroutine func01( a ) bind(C,name="func01")
!DEC$ ATTRIBUTES DLLEXPORT :: func01
implicit none
character(len=1), dimension(90) , intent(in) :: a
character(len=30), dimension(3) :: b
integer*4 :: count,i,j
count=1
do j=1,3
b(J)=''
do I=1,30
b(J)=trim(b(J))//a(count)
count=count+1
enddo
enddo
print *
print *, "char length = ", len(b(1)), len(b(2)), len(b(3))
print *, "raw a(1) : [", b(1), "]"
print *, "raw a(2) : [", b(2), "]"
print *, "raw a(3) : [", b(3), "]"
print *, "trim : [", trim(b(1)), "] [", trim(b(2)), "] [", trim(b(3)), "]"
end
FUNCTION SUMANDTIMES(P, length1, Q) bind(C,name="SUMANDTIMES")
!DEC$ ATTRIBUTES DLLEXPORT :: SUMANDTIMES
implicit none
integer::length1
real, dimension(*):: P
real :: SUMANDTIMES, Q
integer::i
print *, "The length1==", length1, ";"
SUMANDTIMES =0.0
do i = 1,length1 ! sum the array elements
SUMANDTIMES = SUMANDTIMES + p(i) * Q
PRINT *,p(i)
end do
RETURN
END FUNCTION
FUNCTION array2by2(P, row, col) bind(C,name="array2by2")
!DEC$ ATTRIBUTES DLLEXPORT :: array2by2
USE ISO_C_BINDING
implicit none
integer::row, col, i, j, array2by2
!real,DIMENSION(row*col)::
real P(*)
real PP(row, col)
print *, "---->row-----", row
print *, "---->col-----", col
do i=1,row
do j=1,col
PP(i,j) = P((i-1)*row+j)
P((i-1)*row+j) = PP(i,j) * 100
print *, PP(i,j), i, j, (i-1)*row+j
end do
print *, "----row-----", i
end do
array2by2 = 0
RETURN
END FUNCTION
Python调用代码如下(dll放在py文件的同一目录)
# coding=utf-8
from _ctypes import byref
from ctypes import cdll, c_int, c_float
import ctypes
my_dll = cdll.LoadLibrary('fortranDLLExample.dll')
result = my_dll.ABZERO(c_int(324))
print "my_dll.ABZERO(c_int(324))==", result, type(result)
my_dll.ABZERO_FLOAT.restype = c_float # 要设置返回值的类型,不然默认会返回int型,导致数据混乱
result = my_dll.ABZERO_FLOAT(c_float(500.44))
print "my_dll.ABZERO_FLOAT(c_float(500.44))", result, type(result)
# tip:dll.addf.argtypes = (c_float, c_float)
# addf 有两个形参,都是 float 类型。虽然也可以用数组设置,但是元祖的效率更高
FloatArray = c_float * 5
ia = FloatArray(5.32, 1.12, 7.321, 33.12, 99.3)
for i in ia:
print i
my_dll.sum.restype = c_float
result = my_dll.sum(byref(c_int(len(ia))), byref(ia))
print "dll.sum == ", result
FloatArray = c_float * 3
ia2 = FloatArray(1.1, 2.2, 3.3)
my_dll.SUMANDTIMES.restype = c_float
result = my_dll.SUMANDTIMES(byref(ia2),
byref(c_int(len(ia2))),
byref(c_float(100.1)))
print "dll.SUMANDTIMES == ", type(result), result
# 出现win32不是有效的应用程序bug的时候,记得在fortran编辑器选择好x86或x64,版本要和python的位数对应上
d = ctypes.create_string_buffer("abcde67890b234567 "
"waeofijo "
"awoijewfawfe ", size=90)
my_dll.func01(d)
j_table = (c_float * 16)(1.1, 1.2, 1.3, 1.4,
2.1, 2.2, 2.3, 2.4,
3.1, 3.2, 3.3, 3.4,
4.1, 4.2, 4.3, 4.4) # 给力
my_dll.array2by2(byref(j_table),
byref(c_int(4)),
byref(c_int(4)))
for i in j_table:
print i,
print "--------------------- 操作完后的结果 ---------------------"
h_table = (c_float * 16)(91.1, 51.2, 1.35, 1.45,
92.1, 52.2, 2.35, 2.45,
93.1, 53.2, 3.35, 3.45,
94.1, 54.2, 4.35, 4.45) # 给力
my_dll.array2by2(byref(h_table),
byref(c_int(4)),
byref(c_int(4)))
for i in h_table:
print i,
print "--------------------- 操作完后的结果 ---------------------"
my_dll.array2by2(byref(j_table),
byref(c_int(4)),
byref(c_int(4)))
for i in j_table:
print i,
print "默认传给dll的是指针,因此在fortran中如果动了地址里面的内容,那么反映到python上也会跟着改变"
输出结果如下:
The p== 324 ;
The p-273 [ 51 ]
my_dll.ABZERO(c_int(324))== 51 <type 'int'>
The p== 500.4400 ;
The p-273 [ 227.2900 ]
my_dll.ABZERO_FLOAT(c_float(500.44)) 227.290008545 <type 'float'>
5.32000017166
1.12000000477
7.32100009918
33.1199989319
99.3000030518
The length1== 5 ;
5.320000
1.120000
7.321000
33.12000
99.30000
dll.sum == 146.180999756
The length1== 3 ;
1.100000
2.200000
3.300000
dll.SUMANDTIMES == <type 'float'> 660.66003418
char length = 30 30 30
raw a(1) : [abcde67890b234567 ]
raw a(2) : [waeofijo ]
raw a(3) : [awoijewfawfe ]
trim : [abcde67890b234567] [waeofijo] [awoijewfawfe]
---->row----- 4
---->col----- 4
1.100000 1 1 1
1.200000 1 2 2
1.300000 1 3 3
1.400000 1 4 4
----row----- 1
2.100000 2 1 5
2.200000 2 2 6
2.300000 2 3 7
2.400000 2 4 8
----row----- 2
3.100000 3 1 9
3.200000 3 2 10
3.300000 3 3 11
3.400000 3 4 12
----row----- 3
4.100000 4 1 13
4.200000 4 2 14
4.300000 4 3 15
4.400000 4 4 16
----row----- 4
110.0 120.000007629 130.0 140.0 209.999984741 220.0 230.0 240.000015259 310.0 320.0 330.0 340.0 410.0 419.999969482 430.000030518 440.0 --------------------- 操作完后的结果 ---------------------
---->row----- 4
---->col----- 4
91.10000 1 1 1
51.20000 1 2 2
1.350000 1 3 3
1.450000 1 4 4
----row----- 1
92.10000 2 1 5
52.20000 2 2 6
2.350000 2 3 7
2.450000 2 4 8
----row----- 2
93.10000 3 1 9
53.20000 3 2 10
3.350000 3 3 11
3.450000 3 4 12
----row----- 3
94.10000 4 1 13
54.20000 4 2 14
4.350000 4 3 15
4.450000 4 4 16
----row----- 4
9110.0 5120.0 135.0 145.0 9210.0 5220.0 234.999984741 245.0 9310.0 5320.0 335.0 345.0 9410.0 5420.0 435.0 444.999969482 --------------------- 操作完后的结果 ---------------------
---->row----- 4
---->col----- 4
110.0000 1 1 1
120.0000 1 2 2
130.0000 1 3 3
140.0000 1 4 4
----row----- 1
210.0000 2 1 5
220.0000 2 2 6
230.0000 2 3 7
240.0000 2 4 8
----row----- 2
310.0000 3 1 9
320.0000 3 2 10
330.0000 3 3 11
340.0000 3 4 12
----row----- 3
410.0000 4 1 13
420.0000 4 2 14
430.0000 4 3 15
440.0000 4 4 16
----row----- 4
11000.0 12000.0009766 13000.0 14000.0 20999.9980469 22000.0 23000.0 24000.0019531 31000.0 32000.0 33000.0 34000.0 41000.0 41999.9960938 43000.0039062 44000.0 默认传给dll的是指针,因此在fortran中如果动了地址里面的内容,那么反映到python上也会跟着改变
关于fortran数组:
Syntactically, assumed shape used colons (:) instead of
an asterisk in the dimension declaration. The difference in meaning
is exactly the subject in question - assumed shape arrays automatically
get their shape information passed, whereas assumed size arrays basically
get nothing but a starting address passed.http://computer-programming-forum.com/49-fortran/f2a81d00123cad00.htm
运行python遇到这个错误 error: Unable to find vcvarsall.bat 可以这么解决:
报错原因:在生成的时候,编译器从%PythonInstallPath%\distutils\msvc9compiler.py里的219行find_vcvarsall(version)函数中找不到vcvarsall.bat文件。
更具体的原因是,msvc9compiler.py从sys.version里提取MSVC的版本号,但是在注册表中并没有根据版本号找到vcvarsall.bat,在系统的环境变量中也没有找到版本号对应的路径。后来我根据版本号,在环境变量中添加了路径,但因为msvc9compiler.py主要是针对VS2008和VS2010所做的路径识别,因此还是不能正确地找到vcvarsall.bat。
解决方法:直接在find_vcvarsall(version)函数中返回vcvarsall.bat的绝对路径。
https://blog.csdn.net/sad_sugar/article/details/73743863
Tip:运行.bat后,相当于添加了vs各种工具的环境变量,我们可以使用dumpbin /symbols xxx.lib来查看lib中有多少function供我们使用
在安装VS 2015期间遇到这么一个问题(即使是去官网下载的版本也会遇到https://www.visualstudio.com/zh-hans/vs/older-downloads/):
setup detected an issue during the operation.
“安装程序检测到一个问题......”
解决方法是:
找到C:\Windows\Fonts目录,
备份fonts下面所有的字体
然后删除C:\Windows\Fonts下面所有的字体(系统字体如果删除不了的,那么就留着,一些字体集提示警告不要删除的,也留着)
然后再安装vs2015就OK了!
这个确实问题很诡异,但就是这么解决的:https://stackoverflow.com/questions/33622151/setup-detected-an-issue-during-visual-studio-community-edition-2015-installation
当出现这个错误的时候Visual Studio cannot debug because a debug target has not been specified或者cannot start debugging because the debug target is missing
(在编译dll的时候尤其容易出现,可以选择一个exe来debug)
编辑VS里的fortran时,如果我们希望开启转跳到定义功能,在这里设置: