The Fortran(90) code is as follows:
! 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
The Python calling code is as follows (dll is placed in the same directory as the py file)
# 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 output is as follows:
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上也会跟着改变
Regarding fortran arrays:
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
Running python encounters this error error: Unable to find vcvarsall.bat It can be solved like this:
Reason for the error: When generating, the compiler cannot find the vcvarsall.bat file from the find_vcvarsall(version) function on line 219 in %PythonInstallPath%\distutils\msvc9compiler.py.
The more specific reason is that msvc9compiler.py extracts the version number of MSVC from sys.version, but does not find vcvarsall.bat according to the version number in the registry, nor does it find the path corresponding to the version number in the system environment variables. Later, I added the path to the environment variable according to the version number, but because msvc9compiler.py is mainly for path recognition for VS2008 and VS2010, it still cannot find vcvarsall.bat correctly.
Solution: Return the absolute path of vcvarsall.bat directly in the find_vcvarsall(version) function.
https://blog.csdn.net/sad_sugar/article/details/73743863
Tip: After running .bat, it is equivalent to adding the environment variables of various tools of vs. We can use dumpbin /symbols xxx.lib to see how many functions are available in the lib for us to use
I encountered such a problem during the installation of VS 2015 (even the version downloaded from the official website will encounter https://www.visualstudio.com/zh-hans/vs/older-downloads/ ):
setup detected an issue during the operation.
"The installer has detected a problem..."
The workaround is:
Find the C:\Windows\Fonts directory,
back up all the fonts under fonts
and delete all the fonts under C:\Windows\Fonts (if the system font cannot be deleted, keep it, some font sets prompt warning not to delete, also Keep it)
and then install vs2015 and it's OK!
This question is really weird, but that's how it was solved: https://stackoverflow.com/questions/33622151/setup-detected-an-issue-during-visual-studio-community-edition-2015-installation
When this error occurs Visual Studio cannot debug because a debug target has not been specified or cannot start debugging because the debug target is missing
(It is especially easy to appear when compiling dll, you can choose an exe to debug)
When editing fortran in VS, if we want to enable the jump to definition function, set it here: